#!/usr/bin/perl  -w
# File displayPipeTracer2.pl

$versionNumber = 23;

=h  REVISION HISTORY:
Version: 		23
Build: 		14
Date:			11/28/2009	
Notes:		
Added functionality to add and edit notes for individual packets.  The packets who have been applied notes are outlined in black.
Added support for new trace files that have an Ack Nak Sequence Number for DLLP packets.  It is also backwards compatible with older trace files.  Similar changes have been made to AnalyzeTrace.pl
Added 'Find Request' and 'Find Completion' for TLP packets.  If there are more than one associated request/completion, a dialog box will appear to cycle through them.

Version: 		22
Build: 		10	
Date:			11/20/2009	
Notes:
Fixed a bug when removing types in data selection.  Now it will not remove cycles where another packet exists.
Added support for new trace files that have an Ack Nak Sequence Number for DLLP packets.  It is also backwards compatible with older trace files.  Similar changes have been made to AnalyzeTrace.pl
Added 'Find Request' and 'Find Completion' for TLP packets.  If there are more than one associated request/completion, a dialog box will appear to cycle through them.

Version: 		21
Build: 		4
Date:			11/05/2009
Notes:
Removed Revision History and added it to the comments section.  Added labels in the status bar to the search functions.  Took out IBM logo to keep file count down.  
Added comments and improved code design.

Version: 		20
Build: 		3	
Date:			11/03/2009	
Notes:
Added Search box with the functions of Port Select, Next, and Previous.  Port Select allows the user to choose a port to search on.  Once a input 
is searched, it will display the number of results found.  The user can cycle through the results using the Next and Previous buttons.  Shortcut 
keys for the Next and Previous are "Enter" and "Shift+Enter", respectively.


Version: 		19	
Build: 		2	
Date:			10/29/2009	
Notes:		
When selecting what data to display under "Data Selection", if removing a packet type, it now removes the blank cycle columns if there are no other 
types in that column. When re-enabling the type, it will add the cycle back in.  It is suggested to remove the type from both corresponding ports 
to keep the cycles lined up.


Version: 		18	
Build: 		1	
Date:			10/28/2009	
Notes:		
Added "Revision History" and "About Display Pipe Tracer" under Help Menu.  Also, an Error Allowance option has been added in the Tx/Rx Analysis.  
This feature allows the user to choose how many errors the analysis goes through before the analysis ends its current check and continues to the next.
=cut

use Tk;
use Tk::Pane;
use XML::DOM;
use Getopt::Long;
use Tk::TableMatrix;
use Tk::Balloon;
use Tk::ROText;

# Packages not used
	# use Tk::BrowseEntry;
	# use Tk::FileDialog;
	# use Tk::Font;
	# use File::Basename;
	# use Tk::Table;
	
use constant NOT_DEBUGGING => 1; # A value of 0 enables NOT_DEBUGGING, 1 disables it


# create the Main Windoow
my $mw	= MainWindow->new;

# Checks what OS the program is running in.  Should be either 'MSWin32' or 'linux'
my $os = $^O;

# Add a title to the Main Window
my $mainTitle = "Pony Pipe Trace Tool";
$mw->title( $mainTitle );

# The "programStatus" variable is bound to the status widget in the main window. As the
#	value of this changes, so does the display on the window.
my( $programStatus ) = "";

# Sets top menu bar with File, Tools, and Help
CreateMainMenu();

# Set window size of the main window
$screenHeight = $mw->screenheight()-115;
$screenWidth  = $mw->screenwidth()-6;
$geometryText = "$screenWidth".+"x$screenHeight+0+0";
$mw->geometry("$geometryText");

# Creates top scrollbar
$parent = $mw->Scrolled('Pane', -height => 2, 
								-scrollbars => 'n')->pack(-side => 'top', -fill => 'x');
$parent->Frame(-width => $screenWidth+1)->pack();
$xscroll = $parent->Subwidget('xscrollbar'); 

# Font size is set to 8 for windows and 7 for linux because fonts seem to appear bigger in linux
$fontSize = '8' if ($os eq 'MSWin32');
$fontSize = '7' if ($os eq 'linux');

# Initialize vlaues
$traceFile = "";
$lastSearch = "";
$lastCompletionCycle = -1;
$lastCompletionPort = -1;
$lastCompletionDirection = " ";

# nextCount is the incremental for the packet array.
$nextCount = 0;

# Create the bottom bar to show Cycle Search, Packet Search, and Program Status Information
CreateStatusLabel();

# Interpret Command Line Arguments
GetOptions("trace=s"=>\$traceFile,
				"help",\&HTMLHelp );

print "trace file = $traceFile\n";

# Process the trace file if given in the command line. 
if ( $traceFile ) {
	ProcessTraceFile($traceFile); 
	
	my $title = "$mainTitle - $traceFile";
	$mw->title( $title );
	$programStatus = "Trace File Loaded";
}
else {
  print "No Trace File Specified\n";
}

# This links the horizontal multi-scrollbar to each port frame
$xscroll->configure(-background => "darkgray", 
					-troughcolor => "gray", 
					-cursor => ['sb_h_double_arrow'],
					-command => sub {
										my( $type,$delta,$units )= @_;
										if($type eq 'scroll')
										{
											foreach my $list (@PortFrames) 
											{
												$list->xview(@_);
											}
										}
										if($type eq 'moveto')
										{
											my $num = 2;
											$num = -2 if ($delta < 0);        
											 
											foreach my $list (@PortFrames) 
											{
												$list->xview('scroll',$num,'units');
											}
										}
									} );

# Apply bindings of CTRL-L, CTRL-K, etc
ApplyBindings();  
# Repeat, Standard for a Tk Program
MainLoop;

sub ProcessTraceFile {
	# Gets the trace file name that was passed into
	local( $traceFileName )	= @_;
	$traceName = $traceFileName;
	
	# Initialize and reset all values to be empty
	@packets = ();
	@portArray = ();
	%HashOfDevices = ();
	%DisplayHash = ();
	%DisplayHashDevice = ();
	%DisplayHashPort = ();
	%PortFrames = ();
	%PortLabels = ();
	%portHash = ();
	@headers = ();
	@currentCycleLabels = ();
	@PortFrames = (); 
	@ports = ();
	my $lastTransactionCycle = 0;	
	
	# Create a new Document object that represents the data in the XML file using the module's built-in parser:
	my $parser = new XML::DOM::Parser;
	$doc = $parser->parsefile ($traceFileName);

	# We should erase any data that's currently in  HashOfDevices	
	# Makes a frame that has a right scrollbar.  This is where all the ports will go
	$allPortsFrame = $mw->Scrolled('Pane',
					               -scrollbars => 'osoe',
					               -height => "$screenWidth",
					               -width => "$screenHeight",
					               -sticky => 'new');
	$allPortsFrame->pack(-side	=> 'top', -anchor => 'nw', -fill => 'both', -expand => 1) if (Exists($allPortsFrame));
	
	
	# This for loop parses the XML file and reads in every single transaction.  It does some presorting and calulations to determine what is in the XML such as types, ports, and device names
	foreach my $transaction ($doc->getElementsByTagName('Transaction')) {
		
		# Gets the Port and Device of each trancaction
		$port = $transaction->getElementsByTagName('DevicePort')->item(0)->getFirstChild->getNodeValue;
	    $device = $transaction->getElementsByTagName('DeviceName')->item(0)->getFirstChild->getNodeValue;
		# Sets up to get how many different ports are being read in
		$portHash{$port} = $port if !(defined $portHash{$port});
		
		# Puts a symbol before each type to use for easier sorting the types later on
		$transactionType = $transaction->getAttribute("type");
		$transactionType = "1" . "Ltssm" if ($transactionType eq "LtssmStateChange");
		$transactionType = "2" . "DLLP" if ($transactionType eq "DLLP");
		$transactionType = "3" . "TLP" if ($transactionType eq "TLP");
		
		# HashOfDevices is a hash of DeviceName, DevicePorts and DeviceTransactions that stores what data is in the xml file
		$HashOfDevices{$device}{$port}{$transactionType}++;
		# Stores another has for devices and ports to make it easier to access keys.
		$DisplayHashDevice{$device} = 1;
		$DisplayHashPort{$port} = 1;
		
		# DisplayHash is similar to HashOfDevices except instead of keeping the count of every Device/Port/Transaction it has a boolen that identifes which to display
	    $DisplayHash{$device}{$port}{$transactionType} = 1;
	}
	
	# Puts the keys of %portHash into an array
	for (sort keys %portHash) {
		push @portArray, $_;
		#$searchOptionMenu->addOptions(["$_" => "$_"]);
	}
	# Stores Search Options
	@searchOptions = reverse(@portArray);
	foreach (@searchOptions) {
		$searchOptionMenu->addOptions(["$_" => "$_"]);
	}
	# Stores size of portArray and prints it
	$numberOfPorts = @portArray;
	print "$numberOfPorts Ports to be Analyzed: @portArray\n";			               
	
	# This is the main loop that goes through each Port and processes each packets. 
	foreach $portIteration (@portArray)
	{ 	
		#Inititialize and reset variables
		%cycleHash = ();
		my $xindex = 0;
		my $yindex = 1;
		my $lastTransactionCycle = 0;
		my $currentTransactionCycle = 0;
		
		# Display status
		print "Processing Port $portIteration\n";
		$programStatus = "Processing Port $portIteration...";
		$statusLabel->configure(-text => "Processing Port $portIteration...");
		
		$PortLabels{$portIteration} = $allPortsFrame->Label(-text => "\nDevice Name: $device, Port: $portIteration", 
															-font => ['Arial',$fontSize,'bold'])->pack(-expand => 1, 
																										-fill => 'both');
		#push @PortLabels, $PortLabel;
		$PortFrames{$portIteration} = $allPortsFrame->Scrolled('TableMatrix',
					                        -resizeborders=>'none',
	                                        -titlerows => 1,
	                                        -titlecols => 1,
	                                        -background => 'white',
	                                        -foreground => 'white',
	                                        -borderwidth => 0,
	                                        -rows => 6,
	                                        -colstretchmode=>'all',
	                                        -cols => 1,
	                                        -colwidth => 25,
											-flashmode => 1,
											-flashtime => 6,
	                                        -cache => 1,
											-maxheight => 400,
											-takefocus => 'always',
											-cursor => ['left_ptr'],
	                                        -scrollbars => "osoe")->pack(-side => "top", 
																		   -fill => 'both', 
																		   -expand => 1);
		# Initialize tags for active cells or disabled cells														   
		$PortFrames{$portIteration}->tagConfigure('dis', -state => 'disabled', -bg => 'white');
		$PortFrames{$portIteration}->tagConfigure('act', -state => 'normal', -bg => 'lightyellow');
		
		# Brings Main Window to focus
		$mw->deiconify;
		
		# Puts left row headers of each Packet type and applies their associative color
		$headerIndex = 0;
		foreach('Cycle Number', 'Ltssm State Change', 'DLLP Rx', 'DLLP Tx', 'TLP Rx', 'TLP Tx'){
			$header = $PortFrames{$portIteration}->Label(-text => "$_", 
										-background => 'blue', 
										-font=> ['Arial',$fontSize,'bold'],
										-cursor => ['left_ptr']);
			$PortFrames{$portIteration}->windowConfigure("$headerIndex,0", -window => $header, -sticky => 'nsew');
			push @headers, $header;
			$header->configure(-background => 'white') if($headerIndex == 0);
			$header->configure(-background => 'violet', -foreground => 'black') if($headerIndex == 1);
			$header->configure(-background => 'orange', -foreground => 'black') if($headerIndex == 2);
			$header->configure(-background => 'yellow', -foreground => 'black') if($headerIndex == 3);
			$header->configure(-background => 'turquoise', -foreground => 'black') if($headerIndex == 4);
			$header->configure(-background => 'green', -foreground => 'black') if($headerIndex == 5);
			$headerIndex++;
		}
		
		# Sets the Cycle Row height to 1 line long
		$PortFrames{$portIteration}->rowHeight(0 => 1);
		
		# Main loop that goes through each transaction in the xml and sorts it calls the respective function to add it to the table
		foreach my $transaction ($doc->getElementsByTagName('Transaction'))
		{
			$currentPort = $transaction->getElementsByTagName('DevicePort')->item(0)->getFirstChild->getNodeValue;
			$currentTransactionCycle = $transaction->getElementsByTagName('Cycle')->item(0)->getFirstChild->getNodeValue;
			
			# If the current transaction being read in is equal to the port the outer loop is on, then it goes into inserting the cell into the table
			if($portIteration eq $currentPort)
			{
				# cycleHash is used for Cycle Searching.  It keeps track of the yindex used for each cycle (key)
				$cycleHash{$currentTransactionCycle} = $yindex;
				# Checks to see whether to insert a new column if the cycle does not match the last cycle.  This is dependent on having the cycles in the trace file being sequential
				if ($lastTransactionCycle != $currentTransactionCycle)
				{
					$yindex++;
					# Inserts a new column and disables all cells for now so the cell won't be normally editable as is default with TableMatrix
					$PortFrames{$portIteration}->insertCols("$yindex.0", 1);
					$PortFrames{$portIteration}->tagCell('dis',"1,$yindex");
					$PortFrames{$portIteration}->tagCell('dis',"2,$yindex");
					$PortFrames{$portIteration}->tagCell('dis',"3,$yindex");
					$PortFrames{$portIteration}->tagCell('dis',"4,$yindex");
					$PortFrames{$portIteration}->tagCell('dis',"5,$yindex");
					$PortFrames{$portIteration}->tagRaise('dis');
					#Puts the cycle at the top
					$xindex = 0;
					PrintCycle($currentTransactionCycle, $yindex);
					# ProcessType sorts it and then sends it to the appopriate type
		    		$xindex = 1;
		    		ProcessType($transaction, $xindex, $yindex, $currentPort, $currentTransactionCycle);
				}
				# Keeps the column the same if the cycle is the same as the last cycle
				elsif ($lastTransactionCycle eq $currentTransactionCycle)
				{
		    		$xindex = 1;
		    		ProcessType($transaction, $xindex, $yindex, $currentPort, $currentTransactionCycle);
				}
				# Keeps track of what the last cycle was
				$lastTransactionCycle = $currentTransactionCycle;
			}
			# Switches port if the current port is not the same as the last and create a blank column to stay alligned
			elsif ($portIteration != $currentPort)
			{
				# If the cycle is not the same as the last, it will create a new column 
				if ($lastTransactionCycle != $currentTransactionCycle)
				{
					$yindex++;
					# Inserts a new column and disables all cells for now so the cell won't be normally editable as is default with TableMatrix
					$PortFrames{$portIteration}->insertCols("$yindex.0", 1);
					$PortFrames{$portIteration}->tagCell('dis',"1,$yindex");
					$PortFrames{$portIteration}->tagCell('dis',"2,$yindex");
					$PortFrames{$portIteration}->tagCell('dis',"3,$yindex");
					$PortFrames{$portIteration}->tagCell('dis',"4,$yindex");
					$PortFrames{$portIteration}->tagCell('dis',"5,$yindex");
					$PortFrames{$portIteration}->tagRaise('dis');
					$xindex = 0;
					PrintCycle($currentTransactionCycle, $yindex);
				}
				elsif ( $lastTransactionCycle eq $currentTransactionCycle )
				{
					$xindex = 0;
				}
				$lastTransactionCycle = $currentTransactionCycle;
			}
		}
		# Keeps an array of PortFrames for use in the horizontal bar at the top
		push @PortFrames, $PortFrames{$portIteration};
		push @ports, $portIteration;
	}
	$portCount = @ports;
	# Assign default port associations.  Odd goes to even and vice versa.  i.e. 1->2, 2->1, 3->4, etc
	for (0 .. $portCount-1) {
		if (($_+1) % 2 == 0) {
			$associatedPorts{$ports[$_]} =  $ports[$_-1];
		}
		elsif (($_+1) % 2 != 0) {
			$associatedPorts{$ports[$_]} =  $ports[$_+1];
		}
	}
}

# PrintCycle simply puts the cycle of the the transaction at the top of the column
sub PrintCycle {
	my ($currentTransactionCycle, $yindex) = @_;
	my $currentCycleLabel = $PortFrames{$portIteration}->Label(-text => "$currentTransactionCycle", 
											  -background => 'white', 
											  -font => ['Arial',$fontSize,'bold'],
											  -cursor => ['left_ptr']);
	$PortFrames{$portIteration}->windowConfigure("0,$yindex", -window => $currentCycleLabel, -sticky => 'nsew');
	push @currentCycleLabels, $currentCycleLabel;
}

# ProcessType sorts the type and calls a function to add it to the table
sub ProcessType() {
	my ($transaction, $xindex, $yindex, $currentPort, $currentTransactionCycle) = @_;
	my $type = $transaction->getAttribute("type");
	# Processes each transaction depending on the type
	if ("$type" eq "LtssmStateChange")
	{
		$xindex = 1;
		CreateStateChange($transaction, $xindex, $yindex, $currentPort, $currentTransactionCycle);
	}
	elsif ("$type" eq "DLLP")
	{
		$direction = $transaction->getElementsByTagName('Direction')->item(0)->getFirstChild->getNodeValue;
		$xindex = 2 if($direction eq "Rx");
		$xindex = 3 if($direction eq "Tx");
		CreateDllp($transaction, $xindex, $yindex, $currentPort, $currentTransactionCycle, $direction);
	}
	elsif ("$type" eq "TLP")
	{	
		$direction = $transaction->getElementsByTagName('Direction')->item(0)->getFirstChild->getNodeValue;	
		$xindex = 4 if($direction eq "Rx");
		$xindex = 5 if($direction eq "Tx");
		CreateTlp($transaction, $xindex, $yindex, $currentPort, $currentTransactionCycle, $direction);
	}	
}

# CreateMainMenu creates the menubar at the top of the window.  It has the options of File, Tools, and Help; each with their associative functions.
sub CreateMainMenu {
	my $menubar = $mw->Menu(-type => 'menubar');
	$mw->configure(-menu => $menubar);
	
	# "File" menu
	my $fileMenu = $menubar->cascade(-label => '~File', -tearoff => 0);
	$fileMenu->command(-label => '~Open Trace File',
					   -accelerator => '(Ctrl+O)',
					   -background =>'white',
					   -activebackground =>'gray',
					   -command => \&OpenFile);
	$fileMenu->command(-label	=> 'Data Selection',
					   -accelerator => '(Ctrl+F)',
					   -background =>'white',
					   -activebackground =>'gray',
					   -command	=> \&DataSelection);
	$fileMenu->command(-label => '~Exit',
					   -background =>'white',
					   -activebackground =>'gray',
					   -command => \&exit);
	
	# "Tools" menu
	my $tools = $menubar->cascade(-label => '~Tools', -tearoff => 0);
	$tools->command(-label	=> 'Trace Statistics',
					   -accelerator => '(Ctrl+D)',
					   -background =>'white',
					   -activebackground =>'gray',
					   -command	=> \&TraceStatistics);
   $tools->command(-label	=> '~Adjust Default Port Associations',
						-background =>'white',
						-activebackground =>'gray',
						-command	=> \&AdjustPortAssociations);
   $tools->command(-label	=> '~Tx/Rx Analysis',
						-accelerator => '(Ctrl+F)',
						-background =>'white',
						-activebackground =>'gray',
						-command	=> \&TxRxAnalysisSetup);
   $tools->command(-label	=> '~Check PSL/Sugar Rules',
						-accelerator => '(Ctrl+P)',
						-background =>'white',
						-activebackground =>'gray',
						-command	=> \&PSLSugar);

	# "Help" menu
	my $helpMenu = $menubar->cascade(-label => '~Help', -tearoff => 0);
	$helpMenu->command(-label	=> '~General Help',
					   -background =>'white',
					   -activebackground =>'gray',
					   -command	=> \&HTMLHelp);
	
	$helpMenu->command(-label	=> '~About Display Pipe Tracer...',
					   -background =>'white',
					   -activebackground =>'gray',
					   -command	=> \&AboutPipeTracer);
	
	# Assign hotkeys to a few functions
	$mw->bind('<Control-o>', [\&OpenFile]);
	$mw->bind('<Control-f>', [\&TraceStatistics]);
	$mw->bind('<Control-d>', [\&DataSelection]);
	$mw->bind('<Control-a>', [\&DataSelection]);
}

# HTMLHelp
sub HTMLHelp {
	my $url = "http://pony.bluehost.ibm.com/wiki/index.php?title=Display_Pipe_Tracer_Tool";
	my $commandline = qq{firefox -new-window $url};
	system($commandline) == 0 or die qq{Couldn't launch '$commandline': $!/$?};
}

# AboutPipeTracer is under the help menu and simply lists the version number of this program
sub AboutPipeTracer {
	my $aboutPipeTracer = new MainWindow;
	$aboutPipeTracer->title("About Pipe Tracer");
	#$IBMimage = $aboutPipeTracer->Photo(-file => 'C:\IBM\IBM_logo.bmp') if ($os eq 'MSWin32');
	#$IBMimage = $aboutPipeTracer->Photo(-file => 'ibm_logo.bmp') if ($os eq 'linux');
	#$aboutPipeTracer->Label(-image=> $IBMimage)->pack();
	$aboutPipeTracer->Label(-text => "IBM\nDisplay Pipe Tracer\nVersion $versionNumber", -justify => 'left')->pack(-anchor => 'w');
	$aboutPipeTracer->Button(-text => 'Exit', -command	=> sub { $aboutPipeTracer->destroy;})->pack(-anchor => 'e', 
																									-expand => 1, 
																									-padx => 5, 
																									-pady => 5);
}

# Allows the user to adjust the default port associations.  This is needed if the ports are not matched up in consecutive pairs of two. Otherwise, the functions find corresponding/completion/request will not be accurate.
sub AdjustPortAssociations {
	$adjustWindow->destroy() if (Exists $adjustWindow);
	my %portAssocHash = ();
	my @defaultPortArray = ();
	$adjustWindow = new MainWindow;
	$adjustWindow->title("Adjust Default Port Associations");
	$adjustWindow->Label(-text => "Current Port Associations", -justify => 'left')->grid(-column => 0, -columnspan => 2, -row => 0);
	my $defaultCounter = 0;
	# This loop is to get the default port mappings to be the initial values in the drop down menu.  1 should go to 2 and 2 should go to 1 by default
	foreach my $portIteration (@portArray) {
		$adjustWindow->Label(-text => "Port $portIteration ", -font => ['Arial',$fontSize], 
									-justify => 'left')->grid(-column => 0, -row => $defaultCounter+1);
		@defaultPortArray = @portArray;
		# Matches odd port with the port before it
		if ($defaultCounter % 2 == 0) {
			my $value = splice @defaultPortArray, $defaultCounter+1, 1;
			splice @defaultPortArray, $defaultCounter, 1;
			unshift (@defaultPortArray, $value); # gets first index of array
		}
		# Matches even port with the port after
		elsif ($defaultCounter % 2 != 0) {
			my $value = splice @defaultPortArray, $defaultCounter-1, 1;
			splice @defaultPortArray, $defaultCounter-1, 1;
			unshift (@defaultPortArray, $value); # gets first index of array
		}
		# Puts the options into the optionmenu
		$adjustWindow->Optionmenu(-options => \@defaultPortArray,
										-background => 'gray90',
										-variable => \$portAssocHash{$portIteration})->grid(-column => 1, -row => $defaultCounter+1);
		$defaultCounter++;
	}
	# Accept and apply the new default Port Associations
	$adjustWindow->Button(-text => "Accept", 
									-font => ['Arial',$fontSize], 
									-command => sub 	{
																	foreach my $portIteration (@portArray) {
																		$associatedPorts{$portIteration} = $portAssocHash{$portIteration};
																		#print "port: $portIteration, association: $portAssocHash{$portIteration}\n";
																	}
																	$adjustWindow->destroy();
																},
									-justify => 'left')->grid(-column => 1, -row => $defaultCounter+1);
}

# A window to define PSL rules and use the psl.pl to check them
sub PSLSugar {
	$pslWindow->destroy() if (Exists $pslWindow);
	$pslWindow = new MainWindow;
	$pslWindow->title("Check PSL/Sugar Rules");
	$pslWindow->Label(-text => "Current Port Associations", -justify => 'left')->grid(-column => 0, -columnspan => 2, -row => 0);
}

# CreateStatusLabel creates the bottom bar which contains the Cycle Search, General Packet Search, and the Program Status
sub CreateStatusLabel {
	my $cycleEntry = "";
	my $searchEntry = "";
	$statusBar = $mw->Frame(-background	=> 'gray',
						    -foreground	=> 'black',
						    -relief		=> 'ridge',
							-borderwidth => 2);	
	$statusBar->pack(-side		=> 'bottom',
					 -expand	=> '1',
					 -anchor	=> 'se',
					 -fill		=> 'x',);
	
	# Create Cycle Search Function followed by a spacer and a horizontal divider
	$statusBar->Label(-text => "Cycle #:", -background	=> 'gray', -anchor => 'se', -font => ['Arial', 8])->pack(-side => 'left');
	$cycleEntryBox = $statusBar->Entry(-textvariable => \$cycleEntry, -font => ['Arial', 8], -bd => 0, -highlightthickness => 0,)->pack(-side => 'left', -fill => 'y');
	my $cycleAccept = $statusBar->Button(-text => "Go to", 
									  -font => ['Arial', 8],
									  -command => sub { \&GoToCycle($cycleEntry) }, 
									  -bd => 1,
									  -highlightthickness => 0)->pack(-side => 'left', -padx => 3, -pady => 1, -fill => 'y');
	$statusBar->Label(-text => " ", -background	=> 'gray', -anchor => 'se', -font => ['Arial', 8])->pack(-side => 'left');
	$statusBar->Label(-background	=> 'gray94', -bd => 0, -anchor => 'se', -font => ['Arial', 1])->pack(-side => 'left', -fill => 'y');

	# Create Packet Search Function 
	$statusBar->Label(-text => "  Search:", -background	=> 'gray', -anchor => 'se', -font => ['Arial', 8])->pack(-side => 'left');
	$searchBox = $statusBar->Entry(-textvariable => \$searchEntry, -font => ['Arial', 8], -bd => 0, -highlightthickness => 1,)->pack(-side => 'left', -fill => 'y');
	@searchOptions = ();  #options added later in ProcessTraceFile()
	$statusBar->Label(-text => "  Port:", -background	=> 'gray', -anchor => 'se', -font => ['Arial', 8])->pack(-side => 'left');
	
	# Put the controls for the search Option
	$searchOptionMenu = $statusBar->Optionmenu(-options => \@searchOptions,
												-font => ['Arial', 8],
												-bd => 1,
												-highlightthickness => 0,
												-variable => \$searchOption )->pack(-side => 'left', -padx => 3, -pady => 1, -fill => 'y');
	my $searchNext = $statusBar->Button(-text => "Next", 
									  -font => ['Arial', 8],
									  -command => sub { \&Search("next", $searchEntry, $searchOption, $statusBar) }, 
									  -bd => 1,
									  -highlightthickness => 0)->pack(-side => 'left', -padx => 3, -pady => 1, -fill => 'y');
	my $searchPrevious = $statusBar->Button(-text => "Previous", 
									  -font => ['Arial', 8],
									  -command => sub { \&Search("previous", $searchEntry, $searchOption, $statusBar) }, 
									  -bd => 1,
									  -highlightthickness => 0)->pack(-side => 'left', -padx => 3, -pady => 1, -fill => 'y');
	
	# If the search text was found, it displays information of how many were found, the number the search is currently on and statistics obaout the result entry
	$foundText = $statusBar->Label(-text => "", -background	=> 'gray', -anchor => 'se', -font => ['Arial', 8, 'bold'])->pack(-side => 'left');
	$statusBar->Label(-text => " ", -background	=> 'gray', -anchor => 'se', -font => ['Arial', 8])->pack(-side => 'left');
	$statusBar->Label(-background	=> 'gray94', -bd => 0, -anchor => 'se', -font => ['Arial', 1])->pack(-side => 'left', -fill => 'y');

	# Bind the Enter key of the cyle and search boxes to perform the Accept button.  For the search, Shift+Enter goes backwards in the search
	$cycleEntryBox->bind('<Key-Return>' => sub { \&GoToCycle($cycleEntry) } );
	$searchBox->bind('<Key-Return>' => sub { \&Search("next", $searchEntry, $searchOption, $statusBar) } );
	$searchBox->bind('<Shift-Key-Return>' => sub { \&Search("previous", $searchEntry, $searchOption, $statusBar) } );
	
	# Provide the status of the program.  This variable changes as the program goes on.
	$statusLabel = $statusBar->Label(-textvariable	=> \$programStatus,
									 -justify		=> 'right',
									 -background	=> 'gray',
									 -foreground	=> 'black',
									 -font => ['Arial', 8],
									 -anchor		=> 'se')->pack(-side => 'right');

}

# OpenFile's function is to open a trace file within the program instead of by command line.  If a trace file already exists, OpenFile deletes the current trace file information so the new one can be loaded
sub OpenFile {
	$programStatus = "Loading trace file...";  
	my $types = [ ['XML Files', '.xml'],
	              ['All Files', '*'],];
	$traceFile = $mw->getOpenFile(-filetypes => $types,
								  -defaultextension => '.xml');
	# Only continues if a trace file was selected.  If the Open Dialog Box closes, OpenFile does nothing
	if($traceFile)
	{
		# If another trace file is already open, this block will delete all previous information
		if (Exists($allPortsFrame)){
			$allPortsFrame->destroy;
			$printOutputWindow->destroy if (Exists($printOutputWindow));
			$statisticsWindow->destroy if (Exists($statisticsWindow));
			$selectionWindow->destroy if (Exists($selectionWindow));
			$statusBar->destroy if (Exists($statusBar));
			$resultsWindow->destroy() if (Exists $resultsWindow);
			$adjustWindow->destroy() if (Exists $adjustWindow);
			%NotesHash = ();
			%switchedPort =();
			undef $lastPort;
			undef $lastRequestPort;
			undef $lastCompletionPort;
			%Packets = ();
			%associatedPorts = ();
			undef @searchArray;
			$lastOption = "";
			$lastSearch = "";
			$nextCount = 0;
		}
		# Recreate the status label
		CreateStatusLabel() if (!Exists($statusBar));
		
		# Waits until all existing data is deleted before processing the ports.  Without this, the new trace file will not be loaded properly
		while (Exists($allPortsFrame) || (Exists($printOutputWindow)) 
				|| (Exists($statisticsWindow)) || (Exists($selectionWindow)))
		{
			$statusLabel->configure(-text => "Closing old data...");
		}
		# Feedback information to the user
		print qq{You chose to open "$traceFile"\n} if $traceFile;
		ProcessTraceFile($traceFile);
		$title = "$mainTitle - $traceFile";
		$mw->title( $title );
		$programStatus = "Trace File Loaded.";
	}
	else { 
		$programStatus = "";
	}
}

# CreateStateChange is called on a LTSSM State Change packet.  It parses the transaction for its data and puts it in the table
sub CreateStateChange {
	# Gets the information from ProcessType so it does not have to be read in again
	my ($transaction, $xindex, $yindex, $DevicePort, $Cycle) = @_;
	my $fillColor = "violet";
	my $activecolor = "blue";
	# Sets height to 2 lines long
	$PortFrames{$portIteration}->rowHeight(1 => 2);
	my $type = 'LTSSM';	
	my $TLPbool = 1;
	
	# Parses XML for the given transaction
	my $DeviceName = $transaction->getElementsByTagName('DeviceName')->item(0)->getFirstChild->getNodeValue;
	my $CurrentState = $transaction->getElementsByTagName('CurrentState')->item(0)->getFirstChild->getNodeValue;
	my $previousState = $transaction->getElementsByTagName('PreviousState')->item(0)->getFirstChild->getNodeValue;
	
	# Sets three text variables each containing a different amount of imformation
	my $text = "$CurrentState";
	my $expandText = "State: $CurrentState\nPrevious State: $previousState";
	my $fullText = "Cycle: $Cycle\nPort: $DevicePort\nTransaction Type: Ltssm State Change\nState: $CurrentState\nPrevious State: $previousState";

	# Hash that is used by Data Selection.  Lets the selection know if there is an LTSSM Packet in this column
	$LTSSMindexes{$yindex}{$DevicePort} = 1;
	# Stores the packet information into an array that is used by the search function
	$searchArray[$nextCount+1] = $DevicePort;
	$searchArray[$nextCount+2] = $yindex;
	$searchArray[$nextCount+3] = $type;
	$searchArray[$nextCount+4] = $fullText;
	$searchArray[$nextCount+5] = $Cycle;
	$searchArray[$nextCount+6] = "";
	$searchArray[$nextCount+7] = " ";
	$nextCount += 7;
	
	# Creates a button for the packet so it can be clicked and will have options
	$Packets{$DevicePort}{$Cycle}{$type}  = $PortFrames{$portIteration}->Menubutton(-activebackground => $activecolor,
															-background => $fillColor,
															-borderwidth => 1,
															-tearoff => 0,
															-text => $text,
															-relief => 'raised',
															-font=>['Arial', $fontSize],
															-justify => 'right', 
															-cursor => ['left_ptr']);
	# Puts the packet into the table
	$PortFrames{$portIteration}->windowConfigure("$xindex,$yindex", -window => $Packets{$DevicePort}{$Cycle}{$type}, -sticky => 'nsew');
	# Creates a ballon that will pop up when the packet is hovered over.  Shows somewhat more details than the standard view
	my $balloon = $PortFrames{$portIteration}->Balloon(-statusbar => $statusLabel, -background => 'tan');
	$balloon->attach($Packets{$DevicePort}{$Cycle}{$type}, -balloonmsg => $expandText, -statusmsg => 'Click for more options');
	# Creates button to call Print State.  Print State will show the full packets information
	$viewPacket{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'View Packet',
						 -activebackground =>'blue',
						 -background => 'gray' ,
						 -command=>[\&ViewPacket, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $Cycle, $type]);
	# Checks if the trace file has a tag for a Note in the trace
	if ($transaction->getElementsByTagName('Note')->item(0) && $transaction->getElementsByTagName('Note')->item(0)->getFirstChild) {
		$notesText{$DevicePort}{$Cycle}{$type} = $transaction->getElementsByTagName('Note')->item(0)->getFirstChild->getNodeValue;
	}
	# If there is note already a note for this packet, it allows an option to add it
	if (!defined $notesText{$DevicePort}{$Cycle}{$type}) {
		$NotesHash{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Add Note',
												-activebackground =>'blue',
												-background => 'gray',
												-command=>[\&AddEditNote, 'Add', $DevicePort, $Cycle, $type, $expandText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount]);
	}
	# Else if the trace file already had a note in the trace, it allows an option to edit it or remove it
	else {
		# Change the oulining of that packet
		$Packets{$DevicePort}{$Cycle}{$type}->configure(-borderwidth => 3, -relief => 'solid');
		# Edits the balloon message to include the note
		$balloonExpandText = $expandText . "\n\nNOTE:\n" . $notesText{$DevicePort}{$Cycle}{$type};
		$fullTextNote = $fullText . "\n\nNOTE:\n" . $notesText{$DevicePort}{$Cycle}{$type};
		$searchArray[$nextCount-3] = $fullTextNote;
		$viewPacket{$DevicePort}{$Cycle}{$type}->configure(-command=>[\&ViewPacket, $xindex, $yindex, $TLPbool, $fullTextNote, $fillColor, $DevicePort, $Cycle, $type]);
		$balloon->attach($Packets{$DevicePort}{$Cycle}{$type}, -balloonmsg => $balloonExpandText, -statusmsg  => 'Click for more options');
		$NotesHash{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Edit Note',
									-activebackground =>'blue',
									-background => 'gray',
									-command=>[\&AddEditNote, 'Edit', $DevicePort, $Cycle, $type, $expandText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount]);
	}
	# Array used by the bindings to change the font of all packets
	push @packets, $Packets{$DevicePort}{$Cycle}{$type};	
	ApplyBindings();
}

# CreateDLLP is called on a DLLP packet, either Tx or Rx.  It parses the transaction for its data and puts it in the table
sub CreateDllp {
	# Gets the information from ProcessType so it does not have to be read in again
	my ($transaction, $xindex, $yindex, $DevicePort, $Cycle, $direction) = @_;
	my $activecolor = "blue";
	my $vcid = ();
	my $headerCredits = ();
	my $payloadCredits = ();
	my $ackNakSequenceNumber = ();
	my ($fillColor, $type, $TLPbool) = NULL;
	# Depending on if the packet is Rx or Tx, it sets a few variables specific for each type
	if ($direction eq "Rx") {
		$fillColor = "orange"; 
		$PortFrames{$portIteration}->rowHeight(2 => 2); 
		$type = 'DLLP Rx'; 
		$TLPbool = 2;
	}
	elsif ($direction eq "Tx") {
		$fillColor = "yellow";
		$PortFrames{$portIteration}->rowHeight(3 => 2);
		$type = 'DLLP Tx';
		$TLPbool = 3;
	}

	# Parses XML for the given transaction
	my $DeviceName = $transaction->getElementsByTagName('DeviceName')->item(0)->getFirstChild->getNodeValue;
	my $Direction = $transaction->getElementsByTagName('Direction')->item(0)->getFirstChild->getNodeValue;
	my $Dword = $transaction->getElementsByTagName('Dword')->item(0)->getFirstChild->getNodeValue;
	my $Crc = $transaction->getElementsByTagName('CRC')->item(0)->getFirstChild->getNodeValue;
	my $dllpType = $transaction->getElementsByTagName('DllpType')->item(0)->getFirstChild->getNodeValue;
	
	# If the trace file is from the new standard, it will have an AckNakSequenceNumber whereas the older ones will not have this.  This makes it compatible with both versions
	if ($dllpType eq 'Ack' || $dllpType eq 'Nak') {
		$ackNakSequenceNumber = $transaction->getElementsByTagName('AckNakSequenceNumber')->item(0);
		if (defined $ackNakSequenceNumber) {
			$ackNakSequenceNumber = $transaction->getElementsByTagName('AckNakSequenceNumber')->item(0)->getFirstChild->getNodeValue;
		}
		undef $vcid; undef $headerCredits; undef $payloadCredits;
	}
	elsif ($dllpType eq 'Init_FC1_P' || $dllpType eq 'Init_FC1_NP' || $dllpType eq 'Init_FC1_Cpl' || $dllpType eq 'Init_FC2_P' || $dllpType eq 'Init_FC2_NP' || $dllpType eq 'Init_FC2_Cpl' 
			|| $dllpType eq 'UpdateFC_P' || $dllpType eq 'UpdateFC_NP' || $dllpType eq 'UpdateFC_Cpl') {
		$vcid = $transaction->getElementsByTagName('VCID')->item(0)->getFirstChild->getNodeValue;
		$headerCredits = $transaction->getElementsByTagName('HeaderCredits')->item(0)->getFirstChild->getNodeValue;
		$payloadCredits = $transaction->getElementsByTagName('PayloadCredits')->item(0)->getFirstChild->getNodeValue;
		undef $ackNakSequenceNumber;
	}
	
	# Sets three text variables each containing a different amount of imformation
	my $text = "Type: $dllpType\nDword: $Dword";
	my $expandText = "CRC: $Crc\nType: $dllpType\nDword: $Dword";
	my $fullText = "Cycle: $Cycle\nPort: $DevicePort\nTransaction Type: DLLP\nDirection: $Direction\nCRC: $Crc\nType: $dllpType\n"
					. "Dword: $Dword";
	my $corresText = "CRC: $Crc\nType: $dllpType\nDword: $Dword";
	
	# If the trace file is from the newer version
	if (defined $ackNakSequenceNumber) {
		$text = $text . "\nSequence Number: $ackNakSequenceNumber";
		$expandText = $expandText . "\nAck Nak Sequence Number: $ackNakSequenceNumber";
		$fullText = $fullText . "\nAck Nak Sequence Number: $ackNakSequenceNumber";
		$corresText = $corresText . "\nAck Nak Sequence Number: $ackNakSequenceNumber";
		$PortFrames{$portIteration}->rowHeight(2 => 3);
		$PortFrames{$portIteration}->rowHeight(3 => 3);
	}
	# Else it is backwards compatible with the old one
	elsif (defined $vcid && defined $headerCredits && defined $payloadCredits) {
		$expandText = $expandText . "\nVCID: $vcid\nHeader Credits: $headerCredits\nPayload Credits: $payloadCredits";
		$fullText = $fullText . "\nVCID: $vcid\nHeader Credits: $headerCredits\nPayload Credits: $payloadCredits";
		$corresText = $corresText . "\nVCID: $vcid\nHeader Credits: $headerCredits\nPayload Credits: $payloadCredits";
	}
	
	# Hash that is used by Data Selection.  Lets the selection know if there is an DLLP Packet in this column
	$DLLPindexes{$yindex}{$DevicePort} = 1; 
	# Stores the packet information into an array that is used by the search function
	$searchArray[$nextCount+1] = $DevicePort;
	$searchArray[$nextCount+2] = $yindex;
	$searchArray[$nextCount+3] = $type;
	$searchArray[$nextCount+4] = $fullText;
	$searchArray[$nextCount+5] = $Cycle;
	$searchArray[$nextCount+6] = $Direction;
	$searchArray[$nextCount+7] = " ";
	$nextCount += 7;
	# Creates a button for the packet so it can be clicked and will have options
	$Packets{$DevicePort}{$Cycle}{$type}  = $PortFrames{$portIteration}->Menubutton(-activebackground => $activecolor,
												-background => $fillColor,
												-borderwidth => 1,
												-tearoff => 0,
												-text => $text,
												-relief => 'raised',
												-font=>['Arial', $fontSize], 
												-cursor => ['left_ptr']);
	# Puts the packet into the table
	$PortFrames{$portIteration}->windowConfigure("$xindex,$yindex", -window => $Packets{$DevicePort}{$Cycle}{$type}, -sticky => 'nsew');
	# Creates a ballon that will pop up when the packet is hovered over.  Shows somewhat more details than the standard view
	my $balloon = $PortFrames{$portIteration}->Balloon(-statusbar => $statusLabel, -background => 'tan');
	$balloon->attach($Packets{$DevicePort}{$Cycle}{$type}, -balloonmsg => $expandText, -statusmsg  => 'Click for more options');
	# Creates button to call Print State.  Print State will show the full packets information
	$viewPacket{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'View Packet',
						 -activebackground =>'blue',
						 -background => 'gray' ,
						 -command=>[\&ViewPacket, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $Cycle, $type]);
	# Checks if the trace file has a tag for a Note in the trace
	if ($transaction->getElementsByTagName('Note')->item(0) && $transaction->getElementsByTagName('Note')->item(0)->getFirstChild) {
		$notesText{$DevicePort}{$Cycle}{$type} = $transaction->getElementsByTagName('Note')->item(0)->getFirstChild->getNodeValue;
	}
	# If there is note already a note for this packet, it allows an option to add it
	if (!defined $notesText{$DevicePort}{$Cycle}{$type}) {
		$NotesHash{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Add Note',
												-activebackground =>'blue',
												-background => 'gray',
												-command=>[\&AddEditNote, 'Add', $DevicePort, $Cycle, $type, $expandText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount]);
	}
	# Else if the trace file already had a note in the trace, it allows an option to edit it or remove it
	else {
		# Change the oulining of that packet
		$Packets{$DevicePort}{$Cycle}{$type}->configure(-borderwidth => 3, -relief => 'solid');
		# Edits the balloon message to include the note
		$balloonExpandText = $expandText . "\n\nNOTE:\n" . $notesText{$DevicePort}{$Cycle}{$type};
		$fullTextNote = $fullText . "\n\nNOTE:\n" . $notesText{$DevicePort}{$Cycle}{$type};
		$searchArray[$nextCount-3] = $fullTextNote;
		$viewPacket{$DevicePort}{$Cycle}{$type}->configure(-command=>[\&ViewPacket, $xindex, $yindex, $TLPbool, $fullTextNote, $fillColor, $DevicePort, $Cycle, $type]);
		$balloon->attach($Packets{$DevicePort}{$Cycle}{$type}, -balloonmsg => $balloonExpandText, -statusmsg  => 'Click for more options');
		$NotesHash{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Edit Note',
									-activebackground =>'blue',
									-background => 'gray',
									-command=>[\&AddEditNote, 'Edit', $DevicePort, $Cycle, $type, $expandText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount]);
	}
	# Creates button to call CorresPacket.  CorresPacket will find the packets in the other ports that match 
	$Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Find Corresponding Packet',
						 -activebackground =>'blue',
						 -background => 'gray' ,
						 -command=>[\&CorresPacket, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $transaction, $DevicePort, $Cycle, $type, $corresText, $Direction]);
	# Array used by the bindings to change the font of all packets
	push @packets, $Packets{$DevicePort}{$Cycle}{$type};	
	ApplyBindings();
}

# CreateTLP is called on a TLP packet, either Tx or Rx.  It parses the transaction for its data and puts it in the table
sub CreateTlp {
	# Gets the information from ProcessType so it does not have to be read in again
	my ($transaction, $xindex, $yindex, $DevicePort, $Cycle, $direction) = @_;
	my( $activecolor ) = "blue";
	my ($fillColor, $type, $TLPbool) = NULL;
	# Depending on if the packet is Rx or Tx, it sets a few variables specific for each type
	if ("$direction" eq "Rx") {
		$fillColor = "turquoise";
		$PortFrames{$portIteration}->rowHeight(4 => 5);
		$type = 'TLP Rx';
		$TLPbool = 4
	}
	elsif ("$direction" eq "Tx") {
		$fillColor = "green";
		$PortFrames{$portIteration}->rowHeight(5 => 5);
		$type = 'TLP Tx';
		$TLPbool = 5;
	}

	# Parses XML for the given transaction
	my $DeviceName = $transaction->getElementsByTagName('DeviceName')->item(0)->getFirstChild->getNodeValue;
	my $Direction = $transaction->getElementsByTagName('Direction')->item(0)->getFirstChild->getNodeValue;
	my $SequenceNumber = $transaction->getElementsByTagName('SequenceNumber')->item(0)->getFirstChild->getNodeValue;
	my $TLPtype = $transaction->getElementsByTagName('TLPtype')->item(0)->getFirstChild->getNodeValue;
	my $TrafficClass = $transaction->getElementsByTagName('trafficClass')->item(0)->getFirstChild->getNodeValue;
	my $Tag = $transaction->getElementsByTagName('Tag')->item(0)->getFirstChild->getNodeValue;
	my $Header =  $transaction->getElementsByTagName('header')->item(0)->getFirstChild->getNodeValue; 
	my $Nullify =  $transaction->getElementsByTagName('Nullify')->item(0)->getFirstChild->getNodeValue; 
	my $firstDWByteEnable = $transaction->getElementsByTagName('FirstDWByteEnable')->item(0)->getFirstChild->getNodeValue;
	my $lastDWByteEnable = $transaction->getElementsByTagName('LastDWByteEnable')->item(0)->getFirstChild->getNodeValue;
	my $format = $transaction->getElementsByTagName('Format')->item(0)->getFirstChild->getNodeValue;
	my $typeOther = $transaction->getElementsByTagName('Type')->item(0)->getFirstChild->getNodeValue;
	my $td = $transaction->getElementsByTagName('TD')->item(0)->getFirstChild->getNodeValue;
	my $ep = $transaction->getElementsByTagName('EP')->item(0)->getFirstChild->getNodeValue;
	# Checks if the TD bit is set and its relation to if there should or should not be a ECRC field
	if ($td == 1) {
		if ($transaction->getElementsByTagName('ECRC')->item(0)) {
			$ecrc = $transaction->getElementsByTagName('ECRC')->item(0)->getFirstChild->getNodeValue;
		}
		else {
			print "ERROR: TD bit at cycle $Cycle on port $DevicePort should be set to 0 if there is no ECRC\n";
			undef $ecrc;
		}
	}
	elsif ($td == 0) {
		if ($transaction->getElementsByTagName('ECRC')->item(0))	{
			print "ERROR: TLP packet at cycle $Cycle on port $DevicePort should not have an ECRC field since TD bit is 0\n";
			$ecrc = $transaction->getElementsByTagName('ECRC')->item(0)->getFirstChild->getNodeValue;
		}
		else {
			undef $ecrc;
		}
	}
	my $lcrc = $transaction->getElementsByTagName('LCRC')->item(0)->getFirstChild->getNodeValue;
	
	($Header, my $payload, my $payloadExpand) = GetPayload($Header, $transaction);
		
	# Sets three text variables each containing a different amount of imformation
	my $text = "SequenceNumber: $SequenceNumber\nTLPtype: $TLPtype\nTrafficClass: $TrafficClass\nTag: $Tag\nNullify: $Nullify";
	my $expandText = "Header: $Header\nSequenceNumber: $SequenceNumber\nTLPtype: $TLPtype\nTrafficClass: $TrafficClass\nTag: $Tag\nNullify: $Nullify\n"
					 . "Payload: $payloadExpand\nFirst DW Byte Enable: $firstDWByteEnable\nLast DW Byte Enable: $lastDWByteEnable\nFormat: $format\n"
					 . "Type: $typeOther\nTD: $td\nEP: $ep"; 
	my $fullText = "Cycle: $Cycle\nPort: $DevicePort\nTransaction Type: TLP\nDirection: $Direction\nHeader: $Header\nSequenceNumber: $SequenceNumber"
					 . "\nTLPtype: $TLPtype\nTrafficClass: $TrafficClass\nTag: $Tag\nNullify: $Nullify\n"
					 . "Payload: \n$payload\nFirst DW Byte Enable: $firstDWByteEnable\nLast DW Byte Enable: $lastDWByteEnable\nFormat: $format\n"
					 . "Type: $typeOther\nTD: $td\nEP: $ep"; 
	my $corresText = "Header: $Header\nSequenceNumber: $SequenceNumber\nTLPtype: $TLPtype\nTrafficClass: $TrafficClass\nTag: $Tag\nNullify: $Nullify\n"
					 . "Payload: \n$payload\nFirst DW Byte Enable: $firstDWByteEnable\nLast DW Byte Enable: $lastDWByteEnable\nFormat: $format\n"
					 . "Type: $typeOther\nTD: $td\nEP: $ep";
	if (defined $ecrc) {	
		$expandText = $expandText . "\nECRC: $ecrc\nLCRC: $lcrc";
		$fullText = $fullText . "\nECRC: $ecrc\nLCRC: $lcrc";
		$corresText = $corresText . "\nECRC: $ecrc\nLCRC: $lcrc";
	}
	elsif (! defined $ecrc) {
		$expandText = $expandText . "\nLCRC: $lcrc";
		$fullText = $fullText . "\nLCRC: $lcrc";
		$corresText = $corresText . "\nLCRC: $lcrc";
	}
	
	if( $Nullify == 1 )
	{
		print "Found a nullified TLP!\n";
		$fillColor='purple';
	}
	
	# Hash that is used by Data Selection.  Lets the selection know if there is an TLP Packet in this column
	$TLPindexes{$yindex}{$DevicePort} = 1; 
	# Stores the packet information into an array that is used by the search function
	$searchArray[$nextCount+1] = $DevicePort;
	$searchArray[$nextCount+2] = $yindex;
	$searchArray[$nextCount+3] = $type;
	$searchArray[$nextCount+4] = $fullText;
	$searchArray[$nextCount+5] = $Cycle;
	$searchArray[$nextCount+6] = $Direction;
	$searchArray[$nextCount+7] = $Header;
	$nextCount += 7;
	
	# Creates a button for the packet so it can be clicked and will have options
	$Packets{$DevicePort}{$Cycle}{$type}  = $PortFrames{$portIteration}->Menubutton(-activebackground => $activecolor,
												-background => $fillColor,
												-borderwidth => 1,
												-tearoff => 0,
												-text => $text,
												-relief => 'raised',
												-font=>['Arial', $fontSize],
												-cursor => ['left_ptr']);
	# Puts the packet into the table
	$PortFrames{$portIteration}->windowConfigure("$xindex,$yindex", -window => $Packets{$DevicePort}{$Cycle}{$type}, -sticky => 'nsew');
	# Creates a ballon that will pop up when the packet is hovered over.  Shows somewhat more details than the standard view
	my $balloon = $PortFrames{$portIteration}->Balloon(-statusbar => $statusLabel, -background => 'tan');
	$balloon->attach($Packets{$DevicePort}{$Cycle}{$type}, -balloonmsg => $expandText, -statusmsg  => 'Click for more options');
	# Creates button to call Print State.  Print State will show the full packets information
	$viewPacket{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'View Packet',
						 -activebackground =>'blue',
						 -background => 'gray' ,
						 -command=>[\&ViewPacket, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $Cycle, $type]);
	# Checks if the trace file has a tag for a Note in the trace
	if ($transaction->getElementsByTagName('Note')->item(0) && $transaction->getElementsByTagName('Note')->item(0)->getFirstChild) {
		$notesText{$DevicePort}{$Cycle}{$type} = $transaction->getElementsByTagName('Note')->item(0)->getFirstChild->getNodeValue;
	}
	
	# If there is note already a note for this packet, it allows an option to add it
	if (!defined $notesText{$DevicePort}{$Cycle}{$type}) {
		$NotesHash{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Add Note',
												-activebackground =>'blue',
												-background => 'gray',
												-command=>[\&AddEditNote, 'Add', $DevicePort, $Cycle, $type, $expandText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount]);
	}
	# Else if the trace file already had a note in the trace, it allows an option to edit it or remove it
	else {
		# Change the oulining of that packet
		$Packets{$DevicePort}{$Cycle}{$type}->configure(-borderwidth => 3, -relief => 'solid');
		# Edits the balloon message to include the note
		$balloonExpandText = $expandText . "\n\nNOTE:\n" . $notesText{$DevicePort}{$Cycle}{$type};
		$fullTextNote = $fullText . "\n\nNOTE:\n" . $notesText{$DevicePort}{$Cycle}{$type};
		$searchArray[$nextCount-3] = $fullTextNote;
		$viewPacket{$DevicePort}{$Cycle}{$type}->configure(-command=>[\&ViewPacket, $xindex, $yindex, $TLPbool, $fullTextNote, $fillColor, $DevicePort, $Cycle, $type]);
		$balloon->attach($Packets{$DevicePort}{$Cycle}{$type}, -balloonmsg => $balloonExpandText, -statusmsg  => 'Click for more options');
		$NotesHash{$DevicePort}{$Cycle}{$type} = $Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Edit Note',
									-activebackground =>'blue',
									-background => 'gray',
									-command=>[\&AddEditNote, 'Edit', $DevicePort, $Cycle, $type, $expandText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount]);
	}
	# Creates button to call CorresPacket.  CorresPacket will find the packets in the other ports that match 
	$Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Find Corresponding Packet',
						 -activebackground =>'blue',
						 -background => 'gray' ,
						 -command=>[\&CorresPacket, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $transaction, $DevicePort, $Cycle, $type, $corresText, $Direction]);
	
	# If the packet is a Non-Posted TLP packet, then it adds an option to find its completion(s)
	if ($TLPtype eq 'MRd64' || $TLPtype eq 'MRd32' || $TLPtype eq 'IORd' ||  $TLPtype eq'IOWr' || $TLPtype eq 'CfgRd0' || $TLPtype eq 'CfgWr0' || $TLPtype eq 'MrdLk32' 
		|| $TLPtype eq 'MrdLk64' || $TLPtype eq 'CfgRd1' || $TLPtype eq 'CfgWr1') {
		$Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Find Completion',
					 -activebackground =>'blue',
					 -background => 'gray' ,
					 -command=>[\&FindCompletion, $xindex, $yindex, $TLPbool, $Header, $fullText, $fillColor, $transaction, $DevicePort, $Cycle, $type, $corresText, $Direction]);
	}
	# If the packet is a Posted TLP packet, then it adds an option to find its request
	elsif ($TLPtype eq 'CplD' || $TLPtype eq 'Cpl' || $TLPtype eq 'CplLk' || $TLPtype eq 'CplDLk') {
		$Packets{$DevicePort}{$Cycle}{$type}->command(-label=>'Find Request',
					 -activebackground =>'blue',
					 -background => 'gray' ,
					 -command=>[\&FindRequest, $xindex, $yindex, $TLPbool, $Header, $fullText, $fillColor, $transaction, $DevicePort, $Cycle, $type, $corresText, $Direction]);
	}
	# Array used by the bindings to change the font of all packets
	push @packets, $Packets{$DevicePort}{$Cycle}{$type};
	ApplyBindings();
}

# GetPayload is used by CreateTLP.  It checks to see if the packet has a payload using the $Header.  If the Header has a 1 in the second bit , then the packet will have a payload
sub GetPayload {
	my ($Header, $transaction) = @_;
	$Header =~ s/^\s+//; #remove leading spaces
	$Header =~ s/\s+$//; #remove trailing spaces
	# Asterisk is needed to avoid undeclared variable warnings
	my $payload = '*';
	my $payloadExpand = "";
	my $payloadLine = "";
	my $firstTwoBytes = substr($Header, 0, 4);
	my $maskResult = 0;
	# And the first two bytes of the header with 0x4000 (big endian) to check the 6th bit and thus determing if the packet has a payload
	$maskResult = hex($firstTwoBytes) & 0x4000;
	if ($maskResult != 0) {
		$payloadLine = $transaction->getElementsByTagName('payload')->item(0)->getFirstChild->getNodeValue;
	}
	else {
		$payloadLine = "No Payload";
	}
	# The payload is read in with a lot of white space and this removes it
	$payloadLine =~ s/^\s+//; #remove leading spaces
	$payloadLine =~ s/\s+$//; #remove trailing spaces
	$payloadLine =~ s/\s+/ /g; #remove more than one space in-between words
	
	# Splits each word of the array and puts it into an array
	my @payloadArray = split(/ /, $payloadLine); #split string into array by spaces
	my $index = 0;
	foreach (@payloadArray) {
		($payload = $payload . "\n") if ($index % 4 == 0 && $index != 0);	#create new line if it has outputed 4 words
		($payload = $payload . "\n") if ($index % 8 == 0 && $index != 0);	#create new line if it has outputed 8 words
		$payload = $payload . "$_ ";
		$index++;
	}	
	$payloadCount = @payloadArray;
	$payloadLine = 'No Payload' if $payloadCount < 1;
	if ($payloadLine ne 'No Payload') {
		for (0 .. 3) { 
			$payloadExpand = $payloadExpand . "$payloadArray[$_] " if defined($payloadArray[$_]);
		}
	}
	elsif ($payloadLine eq 'No Payload') {
		$payloadExpand = "No Payload";
	}
	$payload = substr($payload, 1);		#remove the asterisk for declaration
	
	return($Header, $payload, $payloadExpand);
}

# ApplyBindings puts various keyboard bindings allowing the user easier ways to perform functions
sub ApplyBindings {
	# CTRL+L increases the font size
	$mw->bind('<Control-l>', sub{
									$fontSize++;
									foreach my $packetFont (@packets)
									{
										$packetFont->configure(-font => ['Arial',$fontSize]);
									}
									foreach my $portIteration (@portArray) {
										$PortFrames{$portIteration}->configure(-font => ['Arial',$fontSize]);
										$PortLabels{$portIteration}->configure(-font => ['Arial',$fontSize,'bold']);
										foreach (@headers)
										{
											$_->configure(-font => ['Arial',$fontSize, 'bold']);
										}
									}
									foreach (@currentCycleLabels){
										$_->configure(-font => ['Arial',$fontSize, 'bold']);
									}
									foreach my $portIteration (@portArray) {
										$PortFrames{$portIteration}->packPropagate(1);
									}
								});
	# CTRL+K decreases the font size
	$mw->bind('<Control-k>', sub{
									$fontSize--;
									foreach my $packetFont (@packets)
									{
										$packetFont->configure(-font => ['Arial',$fontSize]);
									}
									foreach my $portIteration (@portArray) {
										$PortFrames{$portIteration}->configure(-font => ['Arial',$fontSize]);
										$PortLabels{$portIteration}->configure(-font => ['Arial',$fontSize,'bold']);
										foreach (@headers)
										{
											$_->configure(-font => ['Arial',$fontSize, 'bold']);
										}
									}
									foreach (@currentCycleLabels){
										$_->configure(-font => ['Arial',$fontSize, 'bold']);
									}
									foreach my $portIteration (@portArray) {
										$PortFrames{$portIteration}->packPropagate(1);
									}
								});
	# CTRL-E brings the ports to the last cycle
	$mw->bind('<Control-e>', sub{
									foreach my $portIteration (@portArray) {
									 	$PortFrames{$portIteration}->see("0,100000");
									}
								});
	# CTRL-W brings the ports to the first cycle
	$mw->bind('<Control-w>', sub{
									foreach my $portIteration (@portArray) {
									 	$PortFrames{$portIteration}->see("0,1");
									}
								});
}

# Search is a function with controls in the status bar that searches through every packet in a port for a given text string.  The search is not case sensitive.  After the Next or Previous buttons are clicked, then a label will show how many matches were found, and the information of the current match.
# Also, the user must select which port to search on using the option menu.  During the search, the current result will be highlighted in blue.  It will stay blue until the next or previous button is pushed.  Also, if the port is switched, the old packet still stays highlighted until another search on that port.
sub Search {
	my ($searchFunction, $searchEntry, $searchOption, $statusBar) = @_;
	print "searchFunction: $searchFunction, searchEntry: $searchEntry, searchOption: $searchOption\n" unless NOT_DEBUGGING;
	# Check to make sure that a trace file is loaded before a search is performed
	my $numOptions = @searchOptions;
	if(@searchOptions == 0) {
		$foundText->configure(-text => "Please Load a Trace");
		return 0;
	}
	# This checks to see if a new search is requested or an old search is wanting to continue on to the next/previous cycle.  If either the search entry or the port option has changed, then it goes into this statement
	if($searchEntry ne $lastSearch || $searchOption ne $lastOption)
	{
		$next = 2;
		$previous = 2;
		$current = 1;
		$count = 0;
		@foundResults = "";
		$size = @searchArray;
		
		# Checks to see if this is a new port
		if (defined $lastPort) {
			# Reset Colors of last packet if the port is the same but the search entry is new
			if ($searchOption eq $lastOption && $searchEntry ne $lastSearch) {
				RecolorPacket($lastPort, $lastCycle, $lastType);
			}
			# If the port has changed regardless of the search entry, it stores the value of the packet at the old port.  Then, if the port is switched to a port that has already been searched upon, it will remove the highlighting
			elsif ($searchOption ne $lastOption) {
				# Checks if the current port to be searched has already been searched upon so it can remove the old highlighting
				if (defined $switchedPort{$searchOption} )
				{
					RecolorPacket($switchedPort{$searchOption}, $switchedCycle{$searchOption}, $switchedType{$searchOption} );
				}
				$switchedPort{$lastPort} = $lastPort;
				$switchedCycle{$lastPort} = $lastCycle;
				$switchedType{$lastPort} = $lastType;
			}
		}
		# Progresses through the searchArray to check each packet for the search entry.  
		for ($j = 0; $j < $size-7; $j += 7) {
			# Only continues if the current packet's port is what equals the search option
			if ($searchArray[$j+1] == $searchOption) {
				$_ = $searchArray[$j+4];
				# This is Pearls syntax for searching a string for specific text.  The /i makes it case insensitive
				if (/$searchEntry/i) {
						$foundResults[$count + 1] = $searchArray[$j+1]; #  DevicePort
						$foundResults[$count + 2] = $searchArray[$j+2]-1; # yindex
						$foundResults[$count + 3] = $searchArray[$j+3]; # type
						$foundResults[$count + 4] = $searchArray[$j+4]; # fullText
						$foundResults[$count + 5] = $searchArray[$j+5]; # cycle
						$foundResults[$count + 6] = $searchArray[$j+6]; # direction
						$foundResults[$count + 7] = $searchArray[$j+7]; # header
						$count += 7;
				}
			}
		}
		$foundCount = $count / 7;
		# Now after the found results have been compiled, it uses the functions Next or Previous to cycle through the results
		if($searchFunction eq 'next' && $count != 0) {
			foreach $portIteration (@portArray) {
				if ($foundResults[1] == $portIteration)
				{	
					$next = 2;
					$previous = $count - 5;
					$PortFrames{$portIteration}->see("0,$foundResults[$next]");
					$current = 1;
					$lastPort = $foundResults[$next-1];
					$lastCycle = $foundResults[$next+3];
					$lastType = $foundResults[$next+1];
					$Packets{$lastPort}{$lastCycle}{$lastType}->configure(-background => 'blue', -foreground => 'white');
					$foundText->configure(-text => "($current/$foundCount) Results Found on Port $lastPort - Displaying $lastType Packet at Cycle $lastCycle");
					$next += 7;
				}
			}
		}
		# Or goes to previous
		elsif($searchFunction eq 'previous' && $count != 0) {
			foreach $portIteration (@portArray) {
				if ($foundResults[1] == $portIteration)
				{
					$next = 2;
					$previous = $count - 5;
					$PortFrames{$portIteration}->see("0,$previous");
					$current = $foundCount;
					$lastPort = $foundResults[$previous-1];
					$lastCycle = $foundResults[$previous+3];
					$lastType = $foundResults[$previous+1];
					#print "port: $lastPort, cycle: $lastCycle, type: $lastType, yindex: $previous\n";
					$Packets{$lastPort}{$lastCycle}{$lastType}->configure(-background => 'blue', -foreground => 'white');
					$foundText->configure(-text => "($current/$foundCount) Results Found on Port $lastPort - Displaying $lastType Packet at Cycle $lastCycle");
					$previous = $previous - 7;
				}
			}
		}
		# If count equals 0, then there was no results found.  
		else {
			$foundText->configure(-text => "No Results Found");
		}
		# Saves the last information to keep track for next search
		$lastOption = $searchOption;
		$lastSearch = $searchEntry;
	}
	# If the search has either a new port option or a new search entry, this statement will allow the user to progress through the results
	else {
		if (!defined($lastType) ) {
			return;
		}
		# Removes the highlighting of the last result
		RecolorPacket($lastPort, $lastCycle, $lastType);
		# Checks for Next or Previous
		if($searchFunction eq 'next') {
			foreach $portIteration (@portArray) {
				if (defined($foundResults[1]) && $foundResults[1] == $portIteration)
				{
					$current++;
					# Checks to see if the current result is the last one. It will loop back to the beginning if it is.
					if ($current > $foundCount)
					{
						$current = 1;
						$previous = $next;
						$next = 2;
					}
					$PortFrames{$portIteration}->see("0,$foundResults[$next]");
					$Packets{$foundResults[$next-1]}{$foundResults[$next+3]}{$foundResults[$next+1]}->configure(-background => 'blue', -foreground => 'white');

					$lastPort = $foundResults[$next-1];
					$lastCycle = $foundResults[$next+3];
					$lastType = $foundResults[$next+1];
					$foundText->configure(-text => "($current/$foundCount) Results Found on Port $lastPort - Displaying $lastType Packet at Cycle $lastCycle");

					$previous = $next - 7;
					$next += 7;
				}
			}
		}
		# Checks for previous
		elsif($searchFunction eq 'previous') {
			foreach $portIteration (@portArray) {
				if (defined($foundResults[1]) && $foundResults[1] == $portIteration)
				{
					$current--;
					# checks to see if the current result is at the beginning.  it will loop back to the end it if is.
					if ($current < 1)
					{
						$current = $foundCount;
						$next = $previous;
						$previous = $count-5;
					}
					$PortFrames{$portIteration}->see("0,$foundResults[$previous]");
					$Packets{$foundResults[$previous-1]}{$foundResults[$previous+3]}{$foundResults[$previous+1]}->configure(-background => 'blue', -foreground => 'white');
					
					$lastPort = $foundResults[$previous-1];
					$lastCycle = $foundResults[$previous+3];
					$lastType = $foundResults[$previous+1];
					$foundText->configure(-text => "($current/$foundCount) Results Found on Port $lastPort - Displaying $lastType Packet at Cycle $lastCycle");
					
					$next = $previous + 7;
					$previous = $previous - 7;
				}
			}
		}
	}
}

# This function is given a the hash of cycles and the cycle.  It will return the yindex of the colum where that cycle is located
sub NextKey {
   my ($h, $key) = @_;

   my $best;
   foreach my $hkey (keys %$h) {
      if ( $hkey >= $key ) {
         if ( !defined($best) || $hkey < $best ) {
            $best = $hkey;
         }
      }
      elsif ( $hkey < $key ) {
         if ( !defined($best) || $hkey > $best ) {
            $best = $hkey;
         }
      }
      print "hkey is $hkey, key is $key, h is $h, best is $best\n" unless NOT_DEBUGGING;
   }
   return $best;
}

# GoToCycle is called when the cycle search is used in the status bar.  It takes a cycle inputted and changes the view of the table to bring the selected cycle into view
sub GoToCycle {
 	my $cycleEntry = $_[0];
	$returnedKey = NextKey(\%cycleHash, $cycleEntry);
 	$column = $cycleHash{$returnedKey} - 1;
	foreach my $portIteration (@portArray) {
	 	$PortFrames{$portIteration}->see("0,$column");
	}
	print ("Cycle Given: $cycleEntry, Column Returned: $column\n") unless NOT_DEBUGGING;
}

# ViewPacket is called when the user left clicks on an individual packet and chooses "Print State".  It opens a new window and displays the complete packet info.  
# The user can click on "Remove" to remove packets from this window. Also, the user can click on "Go To" to change the view of all of the ports to bring the selected packet in view 
sub ViewPacket {
	my ($xindex, $yindex, $TLPbool, $fullText, $fillColor, $port, $cycle, $type) = @_;
	
	my $packetWindowHeight = 450;
	my $packetWindowWidth = 350;
	# Only makes  a new window if one does not already exist
	if (! Exists($printOutputWindow)){
		my $packetsDisplayed = 0;
		$printOutputWindow = MainWindow->new;
		$printOutputWindow->title("Packet Selection");
		$printOutputWindow->Label(-text => "Selected Packets\t",
								  -font=> ['Arial',10,'bold'])->pack(-side => 'top');
		$printOutput = $printOutputWindow->Scrolled('Pane', -scrollbars => 'osoe', 
															-height => $packetWindowHeight,
															-width => $packetWindowWidth, 
															-sticky => 'nw')->pack(-fill => 'both', 
																				   -expand => 1, 
																				   -anchor => 'nw');
		$printXindex = 1; 
	}
	# Brings the print output window into view
	else {
		$printOutputWindow->deiconify;
	}
	
	
	
	$packetsDisplayed++;
	# Changes the vertical size of the print output window depending on how many packets are dispalyed
	if($packetsDisplayed > 3) {
		$geometryText = "$packetWindowWidth".+"x$screenHeight+0+0";
		$printOutputWindow->geometry("$geometryText");
	}
	elsif($packetsDisplayed <= 3) {
		$packetWindowHeight = 450;
		$geometryText = "$packetWindowWidth".+"x$packetWindowHeight+0+0";
		$printOutputWindow->geometry("$geometryText");
	}
	
	# Creates a box for the text to go into
	my $cycleText = $printOutput->Scrolled('ROText', -relief => 'sunken',
									-background => $fillColor, 
									-width => 43,
									-scrollbars => 'osoe')->grid(-row => $printXindex, 
															   -column => 0, 
															   -columnspan => 3, 
															   -sticky => 'nsew');
	# Adjusts number of lines to display initially depending on what type of packet it is
	$cycleText->configure(-height => 4,) if ($TLPbool == 1);
	$cycleText->configure(-height => 6) if ($TLPbool == 2 || $TLPbool == 3);
	$cycleText->configure(-height => 11) if ($TLPbool == 4 || $TLPbool == 5);
	# Insert the full text into the packet
	$cycleText->insert('end', "$fullText");
	
	# Go To button brings the packet into view for the port it is located on
	my $goToButton = $printOutput->Button(-text => "Go to", 
						 				  -command => sub{ 
															foreach my $portIteration (@portArray) {
																if ($portIteration == $port) {
																	$yindexSee = $yindex-3;
																	$PortFrames{$portIteration}->see("$xindex, $yindexSee");
																	# update is necessary because the packet will flash without it being in view
																	$mw->update;
																	$Packets{$portIteration}{$cycle}{$type}->configure(-background => 'blue', -foreground => 'white');
																	$mw->update;
																	# This is a delay for 200 ms to alternate packet backgrounds
																	$mw->after(200);
																	$Packets{$portIteration}{$cycle}{$type}->configure(-background => $fillColor);
																	$mw->update;
																	$mw->after(200);
																	$Packets{$portIteration}{$cycle}{$type}->configure(-background => 'blue', -foreground => 'white');
																	$mw->update;
																	$mw->after(200);
																	$Packets{$portIteration}{$cycle}{$type}->configure(-background => $fillColor);
																}
															} 
													  })->grid(-row => $printXindex+1, 
															   -column => 0, 
															   -sticky => 'nsew');
	my $spacer = $printOutput->Label(-text => "\n", 
									 -font=> ['Arial',6])->grid(-row => $printXindex+2, 
																		  -column => 0, 
																		  -sticky => 'nsew');
	my $removeButton = $printOutput->Button(-text => "Remove", 
						 					-command => sub{
						 										$cycleText->destroy;
						 										$goToButton->destroy;
						 										$spacer->destroy;
						 										$packetsDisplayed--;
															})->grid(-row => $printXindex+1, -column => 1, -sticky => 'nsew');
	# Can't remove the removeButton in the command for it.  It has to be binded in a seperate command
	$removeButton->bind( '<ButtonRelease-1>', sub{$removeButton->destroy;} );
	$printXindex = $printXindex + 3;
}

# This opens a window to add a note or edit an existing note.  There is also an option to delete the note althogether
sub AddEditNote {
	my ($function, $port, $cycle, $type, $balloonText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount) = @_;
	$noteBox->destroy() if (Exists $noteBox);
	$noteBox = new MainWindow;
	$noteBox->title("Add/Edit Note");
	$noteBox->Label(-text => "Notes for $type packet on Port $port, Cycle $cycle", -justify => 'left')->grid(-column => 0, -columnspan => 3, -row => 0);
	# Text Box that allows the user to edit existing notes or make a new one
	$notesTextBox = $noteBox->Scrolled('Text', -relief => 'sunken',
									-width => 50,
									-height => 16,
									-background => 'gray90',
									-scrollbars => 'osoe',
									-selectbackground => 'gray60',)->grid(-row => 1, 
																-column => 0,
																-columnspan => 3,
																-padx => 5,
																-sticky => 'nsew');
	if ($function eq 'Edit') {
		$notesTextBox->insert('end', $notesText{$port}{$cycle}{$type});
	}
	# Save the note. The packet will now be outlined in black and will have the option to 'Edit Note'
	$noteBox->Button(-text => 'Save', -command => sub 	{	
					$notesText{$port}{$cycle}{$type} = $notesTextBox->get("1.0", 'end');
					$NotesHash{$port}{$cycle}{$type}->configure(-label=>'Edit Note', -command=>[\&AddEditNote, 'Edit', $port, $cycle, $type, $balloonText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount]);

					# If the transaction already has a note, it deletes the old tag from the trace
					if ($transaction->getElementsByTagName('Note')->item(0) && $transaction->getElementsByTagName('Note')->item(0)->getFirstChild) {
						$note = $transaction->getElementsByTagName('Note')->item(0)->getFirstChild;
						$note = $note->getParentNode();
						$transaction->removeChild($note);
					}

					# Add the note to the full text so it is editablle
					$fullTextNote = $fullText . "\n\nNOTE:\n" . $notesText{$port}{$cycle}{$type};
					# Add the note to the array so it can be searched upon
					$searchArray[$nextCount-3] = $fullTextNote;
					# Change the view packet function to include the note
					$viewPacket{$port}{$cycle}{$type}->configure(-command=>[\&ViewPacket, $xindex, $yindex, $TLPbool, $fullTextNote, $fillColor, $port, $cycle, $type]);

					# Prepare the XML Tag
					$new = $doc->createElement("Note");
					$text = $doc->createTextNode($notesText{$port}{$cycle}{$type});
					$new->appendChild($text);
					@p = $transaction->getChildNodes();
					$p = $p[0]->getParentNode();
					# Put the tag at the end of the transaction
					$p->insertBefore($new);
					# This is where the trace is actually updated
					$doc->printToFile($traceName);

					$Packets{$port}{$cycle}{$type}->configure(-borderwidth => 3, -relief => 'solid');
					$noteBox->destroy() if (Exists $noteBox);
					# Update the baloon to show the note
					$balloonNoteText = $balloonText . "\n\nNOTE:\n" . $notesText{$port}{$cycle}{$type};
					$balloon->attach($Packets{$port}{$cycle}{$type}, -balloonmsg => $balloonNoteText, -statusmsg  => 'Click for more options');
				})->grid(-row => 2, -column => 0, -padx => 5, -sticky => 'nsew');
	# Delete note.  It removes the black outlining and changes the border back to white
	$noteBox->Button(-text => 'Delete', -command => sub {
					# Remove the tag from the xml if it exists
					if ($transaction->getElementsByTagName('Note')->item(0) && $transaction->getElementsByTagName('Note')->item(0)->getFirstChild) {
						$note = $transaction->getElementsByTagName('Note')->item(0)->getFirstChild;
						$note = $note->getParentNode();
						$transaction->removeChild($note);
						$doc->printToFile($traceName);
					}
					
					$notesText{$port}{$cycle}{$type} = "";
					# Remove the full text from the note, the View Packet function, and the search database
					$fullTextNote = $fullText;
					$searchArray[$nextCount-3] = $fullText;
					$viewPacket{$port}{$cycle}{$type}->configure(-command=>[\&ViewPacket, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $port, $cycle, $type]);
					
					$notesTextBox->delete("1.0", 'end');
					$NotesHash{$port}{$cycle}{$type}->configure(-label=>'Add Note', -command=>[\&AddEditNote, 'Add', $port, $cycle, $type, $balloonText, $balloon, $transaction, $xindex, $yindex, $TLPbool, $fullText, $fillColor, $DevicePort, $nextCount]);
					$Packets{$port}{$cycle}{$type}->configure(-borderwidth => 1, -relief => 'raised');
					# Update the baloon to show the note
					$balloon->attach($Packets{$port}{$cycle}{$type}, -balloonmsg => $balloonText, -statusmsg  => 'Click for more options');
					$noteBox->destroy() if (Exists $noteBox);
				})->grid(-row => 2, -column => 1, -padx => 5, -sticky => 'nsew');
	
	# Close the note box and do nothing else
	$noteBox->Button(-text => 'Cancel', -command => sub {
					$noteBox->destroy() if (Exists $noteBox);
				})->grid(-row => 2, -column => 2, -padx => 5, -sticky => 'nsew');
}

# ViewPacket is called when the user left clicks on an individual packet and chooses "Print State".  It opens a new window and displays the complete packet info.  
# The user can click on "Remove" to remove packets from this window. Also, the user can click on "Go To" to change the view of all of the ports to bring the selected packet in view 
sub CorresPacket {
	my ($xindex, $yindex, $TLPbool, $fullText, $fillColor, $transactionD, $port, $cycle, $type, $corresText, $Direction) = @_;
	$size = @searchArray;
	$count = 0;
	@foundResults = ();
	
	for ($j = 0; $j < $size-7; $j += 7) {
		# Only continues if the current packet's port is what equals the search option
		if ($searchArray[$j+1] == $associatedPorts{$port} && $searchArray[$j+6] ne $Direction ) {
			$_ = $searchArray[$j+4];
			if ($searchArray[$j+5] < $cycle && $Direction eq 'Tx') {
				next;
			}
			elsif ($searchArray[$j+5] > $cycle && $Direction eq 'Rx') {
				next;
			}
			# This is Pearls syntax for searching a string for specific text.  The /i makes it case insensitive
			if (/$corresText/i) {
					$foundResults[$count + 1] = $searchArray[$j+1];	#  Port
					$foundResults[$count + 2] = $searchArray[$j+2]-1; # yindex
					$foundResults[$count + 3] = $searchArray[$j+3]; # type
					$foundResults[$count + 4] = $searchArray[$j+4]; # fullText
					$foundResults[$count + 5] = $searchArray[$j+5]; # cycle
					$foundResults[$count + 6] = $searchArray[$j+6]; # direction
					$foundResults[$count + 7] = $searchArray[$j+7]; # TLP header
					$count += 7;
			}
		}
	}
	$foundCount = $count / 7;
	# If it couldn't find any matches, it will inform the user with a box
	if ($foundCount == 0) {
		$resultsWindow->destroy() if (Exists $resultsWindow);
		$resultsWindow = new MainWindow;
		my $resultText = $resultsWindow->Label(-text => "No Corresponding Packet Found", 
											-font => ['Arial', $fontSize+2, 'bold'],
											-foreground => 'red',
											-justify => 'center')->pack(-side => 'top', 
											-anchor => 'w');
		return;
	}
	$PortFrames{$foundResults[1]}->see("0,$foundResults[2]");
	# update is necessary because the packet will flash without it being in view
	FlashPacket($foundResults[1], $foundResults[5], $foundResults[3]);
	
	for ($j = 0; $j < $count; $j += 7) {
		print "result: ", $j/7+1, ": $foundResults[$j + 5], port: $foundResults[$j + 1]\n" unless NOT_DEBUGGING;
	}
}

# Takes in the indices of the packet and flashes it blue twice 
sub FlashPacket {
	my ($port, $cycle, $type) = @_;
	$mw->update;
	$Packets{$port}{$cycle}{$type}->configure(-background => 'blue', -foreground => 'white');
	$mw->update;
	# This is a delay for 200 ms to alternate packet backgrounds
	$mw->after(200);
	RecolorPacket($port, $cycle, $type);
	$mw->update;
	$mw->after(200);
	$Packets{$port}{$cycle}{$type}->configure(-background => 'blue', -foreground => 'white');
	$mw->update;
	$mw->after(200);
	RecolorPacket($port, $cycle, $type);
	$mw->after(200);
}

# Recolor the packet to its original color based on what type it is
sub RecolorPacket {
	my ($port, $cycle, $type) = @_;
	
	$Packets{$port}{$cycle}{$type}->configure(-background => 'violet', -foreground => 'black') if $type eq 'LTSSM';
	$Packets{$port}{$cycle}{$type}->configure(-background => 'orange', -foreground => 'black') if $type eq 'DLLP Rx';
	$Packets{$port}{$cycle}{$type}->configure(-background => 'yellow', -foreground => 'black') if $type eq 'DLLP Tx';
	$Packets{$port}{$cycle}{$type}->configure(-background => 'turquoise', -foreground => 'black') if $type eq 'TLP Rx';
	$Packets{$port}{$cycle}{$type}->configure(-background => 'green', -foreground => 'black') if $type eq 'TLP Tx';
}
# ViewPacket is called when the user left clicks on an individual packet and chooses "Print State".  It opens a new window and displays the complete packet info.  
# The user can click on "Remove" to remove packets from this window. Also, the user can click on "Go To" to change the view of all of the ports to bring the selected packet in view 

# Simple function that converts the given input value to binary
sub HexToBinary{
	my(%h)=('0'=>'0000','1'=>'0001','2'=>'0010','3'=>'0011','4'=>'0100','5'=>'0101','6'=>'0110','7'=>'0111','8'=>'1000','9'=>'1001','A'=>'1010','B'=>'1011','C'=>'1100','D'=>'1101','E'=>'1110','F'=>'1111');
	$_=uc $_[0];
	s/([0-9A-F])/$h{$1}/g;
	return $_;
};

# FindRequest is a function that is colled on at a Completion Packet and finds its request.  It checks the Requestor ID and Tag
sub FindRequest {
	my ($xindex, $yindex, $TLPbool, $givenHeader, $fullText, $fillColor, $transactionD, $port, $cycle, $type, $corresText, $Direction) = @_;

	my $size = @searchArray;
	my $index = 0;
	my @requestResults = ();
	my $requestsCount = 0;
	RecolorPacket($lastRequestPort, $lastRequestCycle, $lastRequestDirection) if (defined $lastRequestPort);
	RecolorPacket($lastCompletionPort, $lastCompletionCycle, $lastCompletionDirection) if (defined $lastCompletionPort);
	if (defined $switchedPort{$port}) { 
		RecolorPacket($switchedPort{$port}, $switchedCycle{$port}, $switchedType{$port})
	}
	
	for ($j = 0; $j < $size-7; $j += 7) {
		# Only continues if the current packet's port is what equals the search option, the header is not empty, and the direction is the same, and the cycle is less than request
		if ($searchArray[$j+1] == $associatedPorts{$port} && $searchArray[$j+7] ne " " && $searchArray[$j+6] eq $Direction && $searchArray[$j+5] <= $cycle) {
			$checkHeader = $searchArray[$j+7];
			$checkHeader =~ s/ //g;	
			$givenHeader =~ s/ //g;	
			
			$checkHeaderSize = length ($checkHeader);
			#$givenHeaderSize = length ($givenHeader);
			$checkHeader1Byte = substr($checkHeader, 0, 2);
			my $checkHeader1Byte = HexToBinary($checkHeader1Byte);
			$checkFmtType = substr($checkHeader1Byte, 1, 7);
			# Makes sure that the request desired is actually a request and not a completion
			if ($checkFmtType eq '0000000' || $checkFmtType eq '0100000' || $checkFmtType eq '0000001' || $checkFmtType eq '0100001' || $checkFmtType eq '0000010' 
				|| $checkFmtType eq '1000010' || $checkFmtType eq '0000100' || $checkFmtType eq '1000100' || $checkFmtType eq '0000101' || $checkFmtType eq '1000101') {
			}
			else {
				next;
			}
			$checkHeaderCompleterTag = substr($checkHeader, 8, 6);
			$givenHeaderCompleterTag = substr($givenHeader, 16, 6);
			# If the request and tag of the completion match a request and tag of a request, it stores it
			if ($checkHeaderCompleterTag eq $givenHeaderCompleterTag) {
				$requestResults[$index + 1] = $searchArray[$j+1];	#  Port
				$requestResults[$index + 2] = $searchArray[$j+2]-1; # yindex
				$requestResults[$index + 3] = $searchArray[$j+3]; # type
				$requestResults[$index + 4] = $searchArray[$j+4]; # fullText
				$requestResults[$index + 5] = $searchArray[$j+5]; # cycle
				$requestResults[$index + 6] = $searchArray[$j+6]; # direction
				$requestResults[$index + 7] = $searchArray[$j+7]; # TLP header
				$index += 7;
			}
		}
	}
	# Stores the last port, cycle, and direction for later use
	$lastRequestPort = $requestResults[1];
	$lastRequestCycle = $requestResults[5];
	$lastRequestDirection = $requestResults[3];
	$requestsCount = 2;
	
	$foundRequestsCount = $index/7;
	# If no results were found, it informs the user
	if ($foundRequestsCount == 0) { 
		$resultsWindow->destroy() if (Exists $resultsWindow);
		$resultsWindow = new MainWindow;
		my $resultText = $resultsWindow->Label(-text => "No Matching Request Found", 
											-font => ['Arial', $fontSize+2, 'bold'],
											-foreground => 'red',
											-justify => 'center')->pack(-side => 'top', 
											-anchor => 'w');
	}
	# If only one result was found, it brings that result into view and flashes the packet
	elsif ($foundRequestsCount == 1) {
		$PortFrames{$requestResults[1]}->see("0,$requestResults[2]");
		FlashPacket($requestResults[1], $requestResults[5], $requestResults[3]);
	}
	# If more than one request was found, it will pop a window to cycle through the results
	elsif ($foundRequestsCount > 1) {
		$resultsWindow->destroy() if (Exists $resultsWindow);
		$resultsWindow = new MainWindow;
		$PortFrames{$requestResults[1]}->see("0,$requestResults[2]");
		$Packets{$requestResults[$requestsCount-1]}{$requestResults[$requestsCount+3]}{$requestResults[$requestsCount+1]}->configure(-background => 'blue', -foreground => 'white');
		my $resultText = $resultsWindow->Label(-text => "(1/$foundRequestsCount) Requests Found", 
											-font => ['Arial', $fontSize+2, 'bold'],
											-justify => 'center')->pack(-side => 'top', 
											-anchor => 'w');
		# Previous Option 
		my $resultsPrevious = $resultsWindow->Button(-text => "Previous", 
										  -font => ['Arial', 8],
										  -command => sub {	
															# If the cycle is at the beginning, it will loop back to the end
															if ($requestsCount > 7)
															{
																$requestsCount -= 7;
																$PortFrames{$requestResults[$requestsCount-1]}->see("0,$requestResults[$requestsCount]");
																$resultsIter = ($requestsCount-2)/7+1;
																$resultText->configure(-text => "($resultsIter/$foundRequestsCount) Requests Found");
																$Packets{$requestResults[$requestsCount-1]}{$requestResults[$requestsCount+3]}{$requestResults[$requestsCount+1]}->configure(-background => 'blue', -foreground => 'white');
															}
															# Decrements the result
															else {
																$requestsCount = $foundRequestsCount*7-5;
																$PortFrames{$requestResults[$requestsCount-1]}->see("0,$requestResults[$requestsCount]");
																$resultText->configure(-text => "($foundRequestsCount/$foundRequestsCount) Requests Found");
																$Packets{$requestResults[$requestsCount-1]}{$requestResults[$requestsCount+3]}{$requestResults[$requestsCount+1]}->configure(-background => 'blue', -foreground => 'white');
															}
															# Changes the background color from blue back to its original color
															RecolorPacket($lastRequestPort, $lastRequestCycle, $lastRequestDirection);
															$lastRequestPort = $requestResults[$requestsCount-1];
															$lastRequestCycle = $requestResults[$requestsCount+3];
															$lastRequestDirection = $requestResults[$requestsCount+1];
														}, 
										  -bd => 1,
										  -highlightthickness => 0)->pack(-side => 'left', -padx => 3, -pady => 1, -fill => 'y');
		# Next Option
		my $resultsNext = $resultsWindow->Button(-text => "Next", 
										  -font => ['Arial', 8],
										  -command => sub { 
															# If the cycle is at the end, it will loop back to the beginning
															if (defined $requestResults[$requestsCount+7])
															{
																$requestsCount += 7;
																$PortFrames{$requestResults[$requestsCount-1]}->see("0,$requestResults[$requestsCount]");
																$Packets{$requestResults[$requestsCount-1]}{$requestResults[$requestsCount+3]}{$requestResults[$requestsCount+1]}->configure(-background => 'blue', -foreground => 'white');
																$resultsIter = ($requestsCount-2)/7+1;
																$resultText->configure(-text => "($resultsIter/$foundRequestsCount) Requests Found");
															}
															# Increments the result
															else {
																$requestsCount = 2;
																$PortFrames{$requestResults[$requestsCount-1]}->see("0,$requestResults[$requestsCount]");
																$resultText->configure(-text => "(1/$foundRequestsCount) Requests Found");
																$Packets{$requestResults[$requestsCount-1]}{$requestResults[$requestsCount+3]}{$requestResults[$requestsCount+1]}->configure(-background => 'blue', -foreground => 'white');
															}
															# Changes the background color from blue back to its original color
															RecolorPacket($lastRequestPort, $lastRequestCycle, $lastRequestDirection);
															$lastRequestPort = $requestResults[$requestsCount-1];
															$lastRequestCycle = $requestResults[$requestsCount+3];
															$lastRequestDirection = $requestResults[$requestsCount+1];
														}, 
										  -bd => 1,
										  -highlightthickness => 0)->pack(-side => 'left', -padx => 3, -pady => 1, -fill => 'y');
	}
}

# FindCompletion is a function that is colled on at a Request Packet and finds its completion(s).  It checks the Requestor ID and Tag
sub FindCompletion {
	my ($xindex, $yindex, $TLPbool, $givenHeader, $fullText, $fillColor, $transactionD, $port, $cycle, $type, $corresText, $Direction) = @_;

	my $size = @searchArray;
	my $index = 0;
	my @completionResults = ();
	my $completionsCount = 0;
	# Recolor any existing packets that may still be highlighted
	RecolorPacket($lastRequestPort, $lastRequestCycle, $lastRequestDirection) if (defined $lastRequestPort);
	RecolorPacket($lastCompletionPort, $lastCompletionCycle, $lastCompletionDirection) if (defined $lastCompletionPort);
	if (defined $switchedPort{$port}) { 
		RecolorPacket($switchedPort{$port}, $switchedCycle{$port}, $switchedType{$port})
	}
	
	for ($j = 0; $j < $size-7; $j += 7) {
		# Only continues if the current packet's port is what equals the search option, the header is not empty, and the direction is the same, and the cycle is greater than request
		if ($searchArray[$j+1] == $associatedPorts{$port} && $searchArray[$j+7] ne " " && $searchArray[$j+6] eq $Direction && $searchArray[$j+5] >= $cycle) {
			$checkHeader = $searchArray[$j+7];
			$checkHeader =~ s/ //g;
			$givenHeader =~ s/ //g;
			$checkHeaderSize = length ($checkHeader);
			if ($checkHeaderSize == 24) {
				my $checkFirstByte = substr($checkHeader, 0, 2);
				my $checkFirstTwoBytesBin = sprintf "%08b", hex( $checkFirstByte);
				$checkFmtTypeBin = substr($checkFirstTwoBytesBin, 1, 7);
				# Only checks if the TLP type is a completion
				if(	$checkFmtTypeBin eq '0001010' || # Cpl
					$checkFmtTypeBin eq '1001010' || # CplD
					$checkFmtTypeBin eq '0001011' || # CplLk
					$checkFmtTypeBin eq '1001011'	   # CplDLk
				) {
					$checkHeaderRequestorTag = substr($checkHeader, 16, 6);
					$givenHeaderRequestorTag = substr($givenHeader, 8, 6);
					# If the request and tag of the request match a request and tag of a completion, it stores it
					if ($checkHeaderRequestorTag eq $givenHeaderRequestorTag) {
						$completionResults[$index + 1] = $searchArray[$j+1];	#  Port
						$completionResults[$index + 2] = $searchArray[$j+2]-1; # yindex
						$completionResults[$index + 3] = $searchArray[$j+3]; # type
						$completionResults[$index + 4] = $searchArray[$j+4]; # fullText
						$completionResults[$index + 5] = $searchArray[$j+5]; # cycle
						$completionResults[$index + 6] = $searchArray[$j+6]; # direction
						$completionResults[$index + 7] = $searchArray[$j+7]; # TLP header
						$index += 7;
					}
				}
				# print "given requestor and tag: \n$checkHeaderRequestorTag\nCheck requestor and tag: \n$givenHeaderRequestorTag\n";
			}
		}
	}
	# Stores the last port, cycle, and direction for later use
	$lastCompletionPort = $completionResults[1];
	$lastCompletionCycle = $completionResults[5];
	$lastCompletionDirection = $completionResults[3];
	$completionsCount = 2;
	
	$foundCompletionsCount = $index/7;
	# If no results were found, it informs the user
	if ($foundCompletionsCount == 0) { 
		$resultsWindow->destroy() if (Exists $resultsWindow);
		$resultsWindow = new MainWindow;
		my $resultText = $resultsWindow->Label(-text => "No Matching Completions Found", 
											-font => ['Arial', $fontSize+2, 'bold'],
											-foreground => 'red',
											-justify => 'center')->pack(-side => 'top', 
											-anchor => 'w');
	}
	# If only one result was found, it brings that result into view and flashes the packet
	elsif ($foundCompletionsCount == 1) {
		$PortFrames{$completionResults[1]}->see("0,$completionResults[2]");
		FlashPacket($completionResults[1], $completionResults[5], $completionResults[3]);
	}
	# If more than one completion was found, it will pop a window to cycle through the results
	elsif ($foundCompletionsCount > 1) {
		$resultsWindow->destroy() if (Exists $resultsWindow);
		$resultsWindow = new MainWindow;
		$PortFrames{$completionResults[1]}->see("0,$completionResults[2]");
		$Packets{$completionResults[$completionsCount-1]}{$completionResults[$completionsCount+3]}{$completionResults[$completionsCount+1]}->configure(-background => 'blue', -foreground => 'white');
		my $resultText = $resultsWindow->Label(-text => "(1/$foundCompletionsCount) Completions Found", 
											-font => ['Arial', $fontSize+2, 'bold'],
											-justify => 'center')->pack(-side => 'top', 
											-anchor => 'w');
		# Previous Option
		my $resultsPrevious = $resultsWindow->Button(-text => "Previous", 
										  -font => ['Arial', 8],
										  -command => sub {	
															# If the cycle is at the beginning, it will loop back to the end
															if ($completionsCount > 7)
															{
																$completionsCount -= 7;
																$PortFrames{$completionResults[$completionsCount-1]}->see("0,$completionResults[$completionsCount]");
																$resultsIter = ($completionsCount-2)/7+1;
																$resultText->configure(-text => "($resultsIter/$foundCompletionsCount) Completions Found");
																$Packets{$completionResults[$completionsCount-1]}{$completionResults[$completionsCount+3]}{$completionResults[$completionsCount+1]}->configure(-background => 'blue', -foreground => 'white');
															}
															# Decrements the result
															else {
																$completionsCount = $foundCompletionsCount*7-5;
																$PortFrames{$completionResults[$completionsCount-1]}->see("0,$completionResults[$completionsCount]");
																$resultText->configure(-text => "($foundCompletionsCount/$foundCompletionsCount) Completions Found");
																$Packets{$completionResults[$completionsCount-1]}{$completionResults[$completionsCount+3]}{$completionResults[$completionsCount+1]}->configure(-background => 'blue', -foreground => 'white');
															}
															# Changes the background color from blue back to its original color
															RecolorPacket($lastCompletionPort, $lastCompletionCycle, $lastCompletionDirection);
															$lastCompletionPort = $completionResults[$completionsCount-1];
															$lastCompletionCycle = $completionResults[$completionsCount+3];
															$lastCompletionDirection = $completionResults[$completionsCount+1];
														}, 
										  -bd => 1,
										  -highlightthickness => 0)->pack(-side => 'left', -padx => 3, -pady => 1, -fill => 'y');
		# Next Option
		my $resultsNext = $resultsWindow->Button(-text => "Next", 
										  -font => ['Arial', 8],
										  -command => sub { 
															# If the cycle is at the end, it will loop back to the beginning
															if (defined $completionResults[$completionsCount+7])
															{
																$completionsCount += 7;
																$PortFrames{$completionResults[$completionsCount-1]}->see("0,$completionResults[$completionsCount]");
																$Packets{$completionResults[$completionsCount-1]}{$completionResults[$completionsCount+3]}{$completionResults[$completionsCount+1]}->configure(-background => 'blue', -foreground => 'white');
																$resultsIter = ($completionsCount-2)/7+1;
																$resultText->configure(-text => "($resultsIter/$foundCompletionsCount) Completions Found");
															}
															# Increments the result
															else {
																$completionsCount = 2;
																$PortFrames{$completionResults[$completionsCount-1]}->see("0,$completionResults[$completionsCount]");
																$resultText->configure(-text => "(1/$foundCompletionsCount) Completions Found");
																$Packets{$completionResults[$completionsCount-1]}{$completionResults[$completionsCount+3]}{$completionResults[$completionsCount+1]}->configure(-background => 'blue', -foreground => 'white');
															}
															# Changes the background color from blue back to its original color
															RecolorPacket($lastCompletionPort, $lastCompletionCycle, $lastCompletionDirection);
															$lastCompletionPort = $completionResults[$completionsCount-1];
															$lastCompletionCycle = $completionResults[$completionsCount+3];
															$lastCompletionDirection = $completionResults[$completionsCount+1];
														}, 
										  -bd => 1,
										  -highlightthickness => 0)->pack(-side => 'left', -padx => 3, -pady => 1, -fill => 'y');
	}
}

# TraceStatistics is called from a button in the Tools menu.  It counts the number of each type of packet and outputs it.
sub TraceStatistics {
	$statisticsWindow->destroy() if (Exists $statisticsWindow);
	$statisticsWindow = new MainWindow;
	$statisticsWindow->title( "Trace Statistics"); 

	for $device ( sort keys %HashOfDevices )
	{
		# Cycles through the devices if there are multiple
		$deviceText = "\nDevice Name: $device\n";
		my $tl = $statisticsWindow->Label(-text => $deviceText, 
											-width => 50, 
											-font => ['Arial', $fontSize+2, 'bold'],
											-justify => 'center')->pack(-side => 'top', 
											-anchor => 'w');
		# Cycles through ports under the current device name
		for $port ( sort keys %{ $HashOfDevices{ $device } } )
		{
			$transactionText = '*';
			print "Port number: $port\n";
			$portText = "Port number: $port";
			# Cycles through the transactions under the current port
			for $transaction ( sort keys %{ $HashOfDevices{ $device }{$port} } )
			{
				$transactionPrint = substr($transaction, 1);
				print "\t$transactionPrint";
				print "s: $HashOfDevices{$device}{$port}{$transaction}\n";
				$transactionText = $transactionText . "    $transactionPrint" . "s: $HashOfDevices{$device}{$port}{$transaction}\n";
			}
			$transactionText = substr($transactionText, 1);
			my $tl = $statisticsWindow->Label(-text => "$portText\n$transactionText", 
												-font => ['Arial',$fontSize],
												-justify => 'left',
												-anchor => 'nw',)->pack(-fill => 'x',
												-side => 'top', 
												-anchor => 'w');
		}
	}
	$statisticsWindow->Button(-text => 'Exit',
								-command => sub{$statisticsWindow->destroy})->pack(-side => "right");
}

# DataSelection allows the user to choose what to display on the ports.  It is sorted under Device Name, then Port, then Packet Type.  They can deselect and select the boxes, and once accepted, it will update the port.   
# Also, if a packet is removed, it checks if any other packets are in that port.  If not, it will remove that column.
sub DataSelection {
	$selectionWindow = new MainWindow;
	$selectionWindow->title( "Data Selection");

	my $top = $selectionWindow->Frame()->pack(-side => 'top', -fill => 'both');
	my $currentRow = 1;
	my @devices = ();
	my @ports = ();
	my @transactions = ();
	
	# Cycle through the devices
	for $device ( sort keys %DisplayHashDevice )
	{
		$top->Checkbutton(-width => 10, -height => 1, -justify => 'left',
							-text => $device, -font =>['Arial', $fontSize], 
							-anchor => 'w',	-variable => \$DisplayHashDevice{$device})->grid(-row => $currentRow++, -column => 1, -sticky => 'nsw');
		for $port ( sort keys %DisplayHashPort )
		{
			$portText = "Port "."$port";
			$ports =  $top->Checkbutton(-width=>10, -height=>1, -justify => 'left',
													-text=>$portText, -font=>['Arial', $fontSize], -anchor => 'w',
													-variable => \$DisplayHashPort{$port})->grid(-row=>$currentRow++,-column=> 2, -sticky => 'nsw');
			push @ports, $ports;
			for $transactionType ( sort keys %{ $DisplayHash{$device}{$port} } )
			{
				# Removes first number of the transaction type and adds a s at the end to make it plural
				$transactionText = substr($transactionType, 1)."s";
				$transactions  = $top->Checkbutton(-width=>10, -height=>1, -justify => 'left',
													-text=>$transactionText, -anchor => 'w', 
													-variable => \$DisplayHash{$device}{$port}{$transactionType},
													-font=>['Arial', $fontSize])->grid(-row=>$currentRow++, -column=> 3, -sticky => 'nsw');
				push @transactions, $transactions;
			}
		}
	}
	# Accept reads the values of the Buttons and confirms the results
	$top->Button(-text => 'Accept', -command => sub{	
			for $device ( sort keys %DisplayHash )
			{
				for $port ( sort keys %{ $DisplayHash{$device} } )
				{
					for $transactionType ( sort keys %{ $DisplayHash{$device}{$port} } )
					{
						# Checks if the checkbutton for LTSSM has been unchecked.  If so, it will remove all LTSSM packets for that port
						if( ($DisplayHash{$device}{$port}{$transactionType} == 0) && ($transactionType eq '1Ltssm') ) {
							$portIndex = 1;
							foreach my $portIteration (@portArray) {
													$PortFrames{$portIteration}->rowHeight(1 => 0) if ($portIteration == $port);
													# Cycle through LTSSMindexes hash
													for my $yindex ( sort keys %LTSSMindexes )
													{
														for $tempPort ( sort keys %{ $LTSSMindexes{$yindex} } )
														{
															# Checks if the column contains a DLLP or TLP packet.  If not, then it will remove that colum from view
															if(!defined($DLLPindexes{$yindex}{$tempPort}) && !defined($TLPindexes{$yindex}{$tempPort})) {
																$PortFrames{$tempPort}->colWidth($yindex-1 => 0) if ($tempPort == $port);
															}
														}
													}
													$portIndex++;
													$PortFrames{$portIteration}->packPropagate(1);
													$PortFrames{$portIteration}->xview();
												 }
						}
						# Puts back the LTSSM packets 
						elsif ( ($DisplayHash{$device}{$port}{$transactionType} == 1) && ($transactionType eq '1Ltssm') ) {
							$portIndex = 1;
							foreach my $portIteration (@portArray) {
													$PortFrames{$portIteration}->rowHeight(1 => 2) if ($portIteration == $port);
													# Cycle through LTSSMindexes hash
													for my $yindex ( sort keys %LTSSMindexes )
													{
														for $tempPort ( sort keys %{ $LTSSMindexes{$yindex} } )
														{
															$PortFrames{$tempPort}->colWidth($yindex-1 => 25) if ($tempPort == $port);
														}
													}
														
													$portIndex++;
													$PortFrames{$portIteration}->packPropagate(1);
													$PortFrames{$portIteration}->xview();
												 }
						}
						# Checks if the checkbutton for DLLP has been unchecked.  If so, it will remove all DLLP packets for that port
						if( ( $DisplayHash{$device}{$port}{$transactionType} == 0) && ($transactionType eq '2DLLP') ) {
							$portIndex = 1;
							foreach my $portIteration (@portArray) {
													$PortFrames{$portIteration}->rowHeight(2 => 0) if ($portIteration == $port);
													$PortFrames{$portIteration}->rowHeight(3 => 0) if ($portIteration == $port);
													
													for my $yindex ( sort keys %DLLPindexes )
													{
														for $tempPort ( sort keys %{ $DLLPindexes{$yindex} } )
														{
															# Checks if the column contains a LTSSM or TLP packet.  If not, then it will remove that colum from view
															if(!defined($LTSSMindexes{$yindex}{$tempPort}) && !defined($TLPindexes{$yindex}{$tempPort})) {
																$PortFrames{$tempPort}->colWidth($yindex-1 => 0) if ($tempPort == $port);
															}
														}
													}
													
													$portIndex++;
													$PortFrames{$portIteration}->packPropagate(1);
													$PortFrames{$portIteration}->xview();
												 }
						}
						# Puts back the DLLP packets 
						elsif ( ($DisplayHash{$device}{$port}{$transactionType} == 1) && ($transactionType eq '2DLLP') ) {
							$portIndex = 1;
							foreach my $portIteration (@portArray) {
														$PortFrames{$portIteration}->rowHeight(2 => 2) if ($portIteration == $port);
														$PortFrames{$portIteration}->rowHeight(3 => 2) if ($portIteration == $port);
														# Cycle through DLLPindexes hash
														for my $yindex ( sort keys %DLLPindexes )
														{
															for $tempPort ( sort keys %{ $DLLPindexes{$yindex} } )
															{
																$PortFrames{$tempPort}->colWidth($yindex-1 => 25) if ($tempPort == $port);
															}
														}
														 
														$portIndex++;
														$PortFrames{$portIteration}->packPropagate(1);
														$PortFrames{$portIteration}->xview();
													 }
						}
						# Checks if the checkbutton for TLP has been unchecked.  If so, it will remove all TLP packets for that port
						if( ($DisplayHash{$device}{$port}{$transactionType} == 0) && ($transactionType eq '3TLP') ) {
							$portIndex = 1;
							foreach my $portIteration (@portArray) {
														$PortFrames{$portIteration}->rowHeight(4 => 0) if ($portIteration == $port);
														$PortFrames{$portIteration}->rowHeight(5 => 0) if ($portIteration == $port);
														# Cycle through TLPindexes
														for my $yindex ( sort keys %TLPindexes )
														{
															for $tempPort ( sort keys %{ $TLPindexes{$yindex} } )
															{
																# Checks if the column contains a LTSSM or DLLP packet.  If not, then it will remove that colum from view
																if(!defined($DLLPindexes{$yindex}{$tempPort}) && !defined($LTSSMindexes{$yindex}{$tempPort})) {
																	$PortFrames{$tempPort}->colWidth($yindex-1 => 0) if ($tempPort == $port);
																}
															}
														}
														$portIndex++;
														$PortFrames{$portIteration}->packPropagate(1);
														$PortFrames{$portIteration}->xview();
												 }
						}
						# Puts back the TLP packets 
						elsif ( ($DisplayHash{$device}{$port}{$transactionType} == 1) && ($transactionType eq '3TLP') ) {
							$portIndex = 1;
							foreach my $portIteration (@portArray) {
														$PortFrames{$portIteration}->rowHeight(4 => 5) if ($portIteration == $port);
														$PortFrames{$portIteration}->rowHeight(5 => 5) if ($portIteration == $port);
														 
														for my $yindex ( sort keys %TLPindexes )
														{
															for $tempPort ( sort keys %{ $TLPindexes{$yindex} } )
															{
																$PortFrames{$tempPort}->colWidth($yindex-1 => 25) if ($tempPort == $port);
															}
														}
														$portIndex++;
														$PortFrames{$portIteration}->packPropagate(1);
														$PortFrames{$portIteration}->xview();
												 }
						}
					}
				}	
			}
			# Remove all Port Frames and Port Labels so only the ones selected will be packed
			foreach my $portIteration (@portArray) {
											 $PortFrames{$portIteration}->packForget();
										 }
			foreach my $portIteration (@portArray) {
											 $PortLabels{$portIteration}->packForget();
										 }
			
			# Go through each port and only pack if the checkbox is checked
			for my $port ( sort keys %DisplayHashPort )
			{
					my $portIndex = 1;
					foreach my $portIteration (@portArray) {
											 $PortLabels{$portIteration}->pack() if ($DisplayHashPort{$portIteration} == 1 && $DisplayHashDevice{$device} == 1);
											 $PortFrames{$portIteration}->pack(-side => "top", 
																		   -fill => 'both', 
																		   -expand => 1) if ($DisplayHashPort{$portIteration} == 1 && $DisplayHashDevice{$device} == 1);
											 $portIndex++;
											 $PortFrames{$portIteration}->packPropagate(1);
										 }
			}
												})->grid(-row=>$currentRow + 1, -column=>1, -sticky => 'nsew');

}

# TxRxAnalysisSetup prepares the analysis.  It requires the user to choose which ports correspond with eachother.  There is an option to have an error allowance.  You can select how many errors to retrieve before the program will halt so it. 
# There are 4 status indicators at the bottom left of the window that will display green if the analysis was successful, red if not. 
sub TxRxAnalysisSetup {
	$TxRxAnalysisWindow->destroy() if (Exists $TxRxAnalysisWindow);
	$TxRxAnalysisWindow = new MainWindow;
	$TxRxAnalysisWindow->setPalette(background => 'white');
	$TxRxAnalysisWindow->title( "Tx/Rx Analysis Tool Configuration");     
	%portMapHash = ();
	$TxRxAnalysisWindow->Label(-text => "\nDescription:", 
							-font => ['Arial',$fontSize,'bold'], -justify => 'left')->grid(-row => 0, 
																		-column => 0,
																		-columnspan => 2,
																		-sticky => 'nsw');
	# Information for user
	$TxRxAnalysisWindow->Label(-text => "This tool will check if every packet received is entirely the same as the transmitted packet.  "
									. "This tool also checks port coherency.", 
								-font => ['Arial',$fontSize], -wraplength => '200',
								-justify => 'left')->grid(-row => 1, 
															-column => 0,
															-columnspan => 2,
															-rowspan => 1,
															-sticky => 'nsew');
	$TxRxAnalysisWindow->Label(-text => "Configure Port Mappings:", 
							-font => ['Arial',$fontSize,'bold'], -justify => 'left')->grid(-row => 2, 
																		-column => 0,
																		-columnspan => 2,
																		-sticky => 'nsw');
	$portIndex = 3;
	$defaultCounter = 0;
	# This loop is to get the default port mappings.  1 should go to 2 and 2 should go to 1 by default
	foreach my $portIteration (@portArray) {
		$TxRxAnalysisWindow->Label(-text => "Counter-port for port: $portIteration ", -font => ['Arial',$fontSize], 
									-justify => 'left')->grid(-row => $portIndex, 
															-column => 0,  
															-sticky => 'nsw');
		@defaultPortArray = @portArray;
		if ($defaultCounter % 2 == 0) {
			my $value = splice @defaultPortArray, $defaultCounter+1, 1;
			splice @defaultPortArray, $defaultCounter, 1;
			unshift (@defaultPortArray, $value); # gets first index of array
		}
		elsif ($defaultCounter % 2 != 0) {
			my $value = splice @defaultPortArray, $defaultCounter-1, 1;
			splice @defaultPortArray, $defaultCounter-1, 1;
			unshift (@defaultPortArray, $value); # gets first index of array
		}
		# Puts the options into the optionmenu
		$TxRxAnalysisWindow->Optionmenu(-options => \@defaultPortArray,
										-background => 'gray90',
										-variable => \$portMapHash{$portIteration} )->grid(-row => $portIndex, 
																						-column => 1,  
																						-sticky => '');
		$portIndex++;
		$defaultCounter++;
	}
	
	# Sets the Error Allowance Label  and optionmenu
	$TxRxAnalysisWindow->Label(-text => "Error Allowance:", 
							-font => ['Arial',$fontSize], -justify => 'left')->grid(-row => $portIndex, 
																					-column => 0,
																					-sticky => 'nsw');
	# By default, the first option will be 15
	@errorOptions = [15,5,10,20,50,'All'];
	$TxRxAnalysisWindow->Optionmenu(-options => @errorOptions,
									-background => 'gray90',
									-variable => \$errorAllowance,
									)->grid(-row => $portIndex++, 
											-column => 1,  
											-sticky => '');
	$analyzeButton = $TxRxAnalysisWindow->Button(-text => 'Analyze!',
													-command => sub{ 
																	TxRxAnalyze(); 
																}, 
													-background => 'gray90',
													-padx => 5, -pady => 5,)->grid(-row => $portIndex, 
																						-column => 1,
																						-sticky => 'swe');
	# When the analyzeButton is pressed, it will display text to show that it is working
	$analyzeButton->bind('<ButtonPress-1>', sub{
													$AnalysisLabel = $TxRxAnalysisWindow->Label(-text => "Analyzing,\nPlease wait...", 
																						-justify => 'left',
																						-font => ['Arial',$fontSize,'bold'])->grid(-row => $portIndex, 
																						-column => 0, 																		
																						-padx => 10,
																						-sticky => 'se');
												});
	$analyzeButton->bind('<ButtonRelease-1>', sub{
													$AnalysisLabel->gridForget();
												});
	
	$TxRxAnalysisWindow->Label(-text => "Results Summary:", 
							-font => ['Arial',$fontSize,'bold'], -justify => 'left')->grid(-row => $portIndex+2, 
																		-column => 0,
																		-columnspan => 2,
																		-sticky => 'nsw');
	# DLLP Box to check if the DLLP was successful
	$TxRxAnalysisWindow->Label(-text => "DLLP Check", 
							-font => ['Arial',$fontSize],
							-justify => 'right')->grid(-row => $portIndex+3, 
														-column => 0,
														-sticky => 'nse');
	$DLLPcheckDisplay = $TxRxAnalysisWindow->Frame(-relief => 'ridge', -borderwidth => 2, -background => 'gray60')->grid(-row => $portIndex+3, 
																							-column => 1,
																							-sticky => '');
	$DLLPcheckDisplayBox = $DLLPcheckDisplay->Label(-text => "    ", -font => ['Arial',5], -background => 'gray70')->pack();

	# DLLP Box to check if the DLLP Port Coherency was successful
	$TxRxAnalysisWindow->Label(-text => "DLLP Port Coherency", 
							-font => ['Arial',$fontSize],
							-justify => 'right')->grid(-row => $portIndex+4, 
														-column => 0,
														-sticky => 'nse');
	$DLLPportCoherencyDisplay = $TxRxAnalysisWindow->Frame(-relief => 'ridge', -borderwidth => 2, -background => 'gray60')->grid(-row => $portIndex+4, 
																							-column => 1,
																							-sticky => '');
	$DLLPportCoherencyDisplayBox = $DLLPportCoherencyDisplay->Label(-text => "    ", -font => ['Arial',5], -background => 'gray70')->pack();
	
	# TLP Box to check if the TLP Port Coherency was successful
	$TxRxAnalysisWindow->Label(-text => "TLP Check", 
							-font => ['Arial',$fontSize],
							-justify => 'right')->grid(-row => $portIndex+5, 
														-column => 0,
														-sticky => 'nse');
	$TLPcheckDisplay = $TxRxAnalysisWindow->Frame(-relief => 'ridge', -borderwidth => 2, -background => 'gray60')->grid(-row => $portIndex+5, 
																							-column => 1,
																							-sticky => '');
	$TLPcheckDisplayBox = $TLPcheckDisplay->Label(-text => "    ",-font => ['Arial',5], -background => 'gray70')->pack();

	# TLP Box to check if the TLP Port Coherency was successful
	$TxRxAnalysisWindow->Label(-text => "TLP Port Coherency", 
							-font => ['Arial',$fontSize],
							-justify => 'right')->grid(-row => $portIndex+6, 
														-column => 0,
														-sticky => 'nse');
	$TLPportCoherencyDisplay = $TxRxAnalysisWindow->Frame(-relief => 'ridge', -borderwidth => 2, -background => 'gray60')->grid(-row => $portIndex+6, 
																							-column => 1,
																							-sticky => '');
	$TLPportCoherencyDisplayBox = $TLPportCoherencyDisplay->Label(-text => "    ", -font => ['Arial',5],  -background => 'gray70')->pack();

	# Text box to put the results in with a label at the top
	$TxRxAnalysisWindow->Label(-text => "\nFull Results:", 
							-font => ['Arial',$fontSize,'bold'])->grid(-row => 0, 
																		-column => 3, 																		
																		-padx => 5,
																		-sticky => 'nsew');
	$resultsBox = $TxRxAnalysisWindow->Scrolled('ROText', -relief => 'sunken',
									-width => 100,
									-height => 32,
									-background => 'gray90',
									-scrollbars => 'ose',
									-selectbackground => 'gray60',)->grid(-row => 1, 
																-column => 3,
																-padx => 5,
																-rowspan => $portIndex+7,
																-sticky => 'nsew');
	$resultsBox->tagConfigure('errorTag', -font => "Arial $fontSize bold");
	$resultsBox->tagConfigure('normalTag', -font => "Courier $fontSize");
}

# TxRxAnalyze calls the seperate script passing the arguments given.  It then checks for specific lines in the returned text to see if it was successful.
sub TxRxAnalyze {
	@passingPortsArray = ();
	# Remove old results
	$resultsBox->selectAll;
	$resultsBox->deleteSelected;
	for (sort keys %portMapHash)
	{
		print "key: $_, portMapHash(): $portMapHash{ $_ }\n" unless NOT_DEBUGGING;
	}
	$lastportMapHash = -1;
	# A couple checks before the analysis runs to make sure the the port mappings are valid
	for my $keys ( sort keys %portMapHash )
	{
		if ($keys == $portMapHash{$keys} || $lastportMapHash == $portMapHash{$keys}) {
			$resultsBox->insert('end', "Error:  Port Mappings Not Valid\n", 'errorTag');
			return;
		}
		print "portMaps: $keys, portMapHash(portMaps): $portMapHash{$keys}\n" unless NOT_DEBUGGING;
		$lastportMapHash = $portMapHash{$keys};
		push @passingPortsArray, "$keys:$portMapHash{$keys}"
	}
	# if using windows, it calls the seperate script
	open SCRIPT, "perl C:\\IBM\\analyzeTrace.pl $errorAllowance $traceFile @passingPortsArray |" or die "script failed: $!" if ($os eq 'MSWin32');
	# if using linux, it calls the seperate script
	open SCRIPT, "perl analyzeTrace.pl $errorAllowance $traceFile @passingPortsArray |" or die "script failed: $!" if ($os eq 'linux');
	
	$DLLPcheckBool = 0;
	$TLPcheckBool = 0;
	$DLLPportCoherencyCheckBool = 0;
	$TLPportCoherencyCheckBool = 0;
	# While the script has not finished it inserts it into the box line by line and also checks to see if the checks were successful
	while (<SCRIPT>) {
		$resultsBox->insert('end', $_);
		$DLLPcheckBool = 1 if($_ =~ /All DLLP packets were successfully matched!/);
		$TLPcheckBool = 1 if($_ =~ /All TLP packets were successfully matched!/);
		$DLLPportCoherencyCheckBool = 1 if($_ =~ /DLLP Port Coherency checking was successfull!/);
		$TLPportCoherencyCheckBool = 1 if($_ =~ /TLP Port Coherency checking was successfull!/);
	}
	
	# Turns the summary boxes green or red depending on if the text saying it was successful was found
	if ($DLLPcheckBool == 1) {
		$DLLPcheckDisplayBox->configure(-background => 'green')
	}
	elsif ($DLLPcheckBool == 0) {
		$DLLPcheckDisplayBox->configure(-background => 'red')
	}
	if ($DLLPportCoherencyCheckBool == 1) {
		$DLLPportCoherencyDisplayBox->configure(-background => 'green')
	}
	elsif ($DLLPportCoherencyCheckBool == 0) {
		$DLLPportCoherencyDisplayBox->configure(-background => 'red')
	}
	if ($TLPcheckBool == 1) {
		$TLPcheckDisplayBox->configure(-background => 'green')
	}
	elsif ($TLPcheckBool == 0) {
		$TLPcheckDisplayBox->configure(-background => 'red')
	}
	if ($TLPportCoherencyCheckBool == 1) {
		$TLPportCoherencyDisplayBox->configure(-background => 'green')
	}
	elsif ($TLPportCoherencyCheckBool == 0) {
		$TLPportCoherencyDisplayBox->configure(-background => 'red')
	}
	
	close SCRIPT;
}
